Ejemplo n.º 1
0
NTSTATUS
AFSTearDownDbgLog()
{

    NTSTATUS ntStatus = STATUS_SUCCESS;

    AFSAcquireExcl( &AFSDbgLogLock,
                    TRUE);

    if( AFSDbgBuffer != NULL)
    {

        ExFreePool( AFSDbgBuffer);
    }

    AFSDbgBuffer = NULL;

    AFSDbgCurrentBuffer = NULL;

    AFSDbgLogRemainingLength = 0;

    AFSReleaseResource( &AFSDbgLogLock);

    return ntStatus;
}
Ejemplo n.º 2
0
NTSTATUS
AFSInsertCcb( IN AFSFcb *Fcb,
              IN AFSCcb *Ccb)
{

    NTSTATUS ntStatus = STATUS_SUCCESS;

    AFSAcquireExcl( &Fcb->NPFcb->CcbListLock,
                    TRUE);

    if( Fcb->CcbListHead == NULL)
    {
        Fcb->CcbListHead = Ccb;
    }
    else
    {
        Fcb->CcbListTail->ListEntry.fLink = (void *)Ccb;

        Ccb->ListEntry.bLink = (void *)Fcb->CcbListTail;
    }

    Fcb->CcbListTail = Ccb;

    SetFlag( Ccb->Flags, CCB_FLAG_INSERTED_CCB_LIST);

    AFSReleaseResource( &Fcb->NPFcb->CcbListLock);

    return ntStatus;
}
Ejemplo n.º 3
0
BOOLEAN
AFSIs64BitProcess( IN ULONGLONG ProcessId)
{

    NTSTATUS ntStatus = STATUS_SUCCESS;
    BOOLEAN bIs64Bit = FALSE;
    AFSProcessCB *pProcessCB = NULL;
    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;

    __Enter
    {

        AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSIs64BitProcess Acquiring Control ProcessTree.TreeLock lock %p 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;
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
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);

        AFSDbgTrace(( 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))
        {

            AFSDbgTrace(( 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:

        AFSDbgTrace(( 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;
}
Ejemplo n.º 7
0
NTSTATUS
AFSRemoveVolume( IN AFSVolumeCB *VolumeCB)
{

    NTSTATUS ntStatus = STATUS_SUCCESS;
    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;

    __Enter
    {

        //
        // Remove the volume from the tree and list
        // Don't process the list information for reserved entries
        //

        if( VolumeCB->ObjectInformation.FileId.Cell != 0)
        {

            if( BooleanFlagOn( VolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE))
            {

                AFSRemoveHashEntry( &pDeviceExt->Specific.RDR.VolumeTree.TreeHead,
                                    &VolumeCB->TreeEntry);
            }

            if( VolumeCB->ListEntry.fLink == NULL)
            {

                pDeviceExt->Specific.RDR.VolumeListTail = (AFSVolumeCB *)VolumeCB->ListEntry.bLink;

                if( pDeviceExt->Specific.RDR.VolumeListTail != NULL)
                {

                    pDeviceExt->Specific.RDR.VolumeListTail->ListEntry.fLink = NULL;
                }
            }
            else
            {

                ((AFSVolumeCB *)(VolumeCB->ListEntry.fLink))->ListEntry.bLink = VolumeCB->ListEntry.bLink;
            }

            if( VolumeCB->ListEntry.bLink == NULL)
            {

                pDeviceExt->Specific.RDR.VolumeListHead = (AFSVolumeCB *)VolumeCB->ListEntry.fLink;

                if( pDeviceExt->Specific.RDR.VolumeListHead != NULL)
                {

                    pDeviceExt->Specific.RDR.VolumeListHead->ListEntry.bLink = NULL;
                }
            }
            else
            {

                ((AFSVolumeCB *)(VolumeCB->ListEntry.bLink))->ListEntry.fLink = VolumeCB->ListEntry.fLink;
            }
        }

        //
        // Remove any PIOctl objects we have
        //

        if( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB != NULL)
        {

            if( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
            {

                AFSRemoveFcb( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
            }

            AFSDeleteObjectInfo( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);

            AFSExFreePool( VolumeCB->ObjectInformation.Specific.Directory.PIOCtlDirectoryCB);
        }

        if( BooleanFlagOn( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_HELD_IN_SERVICE))
        {

            //
            // Release the fid in the service
            //

            AFSReleaseFid( &VolumeCB->ObjectInformation.FileId);
        }

        //
        // Free up the memory
        //

        if( VolumeCB->NonPagedVcb != NULL)
        {

            if( ExIsResourceAcquiredLite( VolumeCB->VolumeLock))
            {
                AFSReleaseResource( VolumeCB->VolumeLock);
            }

            ExDeleteResourceLite( &VolumeCB->NonPagedVcb->VolumeLock);

            ExDeleteResourceLite( &VolumeCB->NonPagedVcb->ObjectInfoTreeLock);

            AFSExFreePool( VolumeCB->NonPagedVcb);
        }

        if( VolumeCB->ObjectInformation.NonPagedInfo != NULL)
        {

            ExDeleteResourceLite( &VolumeCB->ObjectInformation.NonPagedInfo->DirectoryNodeHdrLock);

            AFSExFreePool( VolumeCB->ObjectInformation.NonPagedInfo);
        }

        if( VolumeCB->DirectoryCB != NULL)
        {

            if( VolumeCB->DirectoryCB->NonPaged != NULL)
            {

                ExDeleteResourceLite( &VolumeCB->DirectoryCB->NonPaged->Lock);

                AFSExFreePool( VolumeCB->DirectoryCB->NonPaged);
            }

            AFSExFreePool( VolumeCB->DirectoryCB);
        }

        AFSExFreePool( VolumeCB);
    }

    return ntStatus;
}
Ejemplo n.º 8
0
NTSTATUS
AFSInitVolume( IN GUID *AuthGroup,
               IN AFSFileID *RootFid,
               OUT AFSVolumeCB **VolumeCB)
{

    NTSTATUS ntStatus = STATUS_SUCCESS;
    IO_STATUS_BLOCK stIoStatus = {0,0};
    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
    AFSNonPagedVolumeCB *pNonPagedVcb = NULL;
    AFSVolumeCB *pVolumeCB = NULL;
    AFSNonPagedObjectInfoCB *pNonPagedObject = NULL;
    ULONGLONG ullIndex = 0;
    BOOLEAN bReleaseLocks = FALSE;
    AFSVolumeInfoCB stVolumeInformation;
    AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;

    __Enter
    {

        //
        // Before grabbing any locks ask the service for the volume information
        // This may be a waste but we need to get this information prior to
        // taking any volume tree locks. Don't do this for any 'reserved' cell entries
        //

        if( RootFid->Cell != 0)
        {

            RtlZeroMemory( &stVolumeInformation,
                           sizeof( AFSVolumeInfoCB));

            ntStatus = AFSRetrieveVolumeInformation( AuthGroup,
                                                     RootFid,
                                                     &stVolumeInformation);

            if( !NT_SUCCESS( ntStatus))
            {

                AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
                              AFS_TRACE_LEVEL_ERROR,
                              "AFSInitVolume AFSRetrieveVolumeInformation(RootFid) failure %08lX\n",
                              ntStatus);

                try_return( ntStatus);
            }

            //
            // Grab our tree locks and see if we raced with someone else
            //

            AFSAcquireExcl( pDeviceExt->Specific.RDR.VolumeTree.TreeLock,
                            TRUE);

            AFSAcquireExcl( &pDeviceExt->Specific.RDR.VolumeListLock,
                            TRUE);

            bReleaseLocks = TRUE;

            ullIndex = AFSCreateHighIndex( RootFid);

            ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.RDR.VolumeTree.TreeHead,
                                           ullIndex,
                                           (AFSBTreeEntry **)&pVolumeCB);

            if( NT_SUCCESS( ntStatus) &&
                pVolumeCB != NULL)
            {

                //
                // So we don't lock with an invalidation call ...
                //

                InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);

                AFSReleaseResource( pDeviceExt->Specific.RDR.VolumeTree.TreeLock);

                AFSReleaseResource( &pDeviceExt->Specific.RDR.VolumeListLock);

                bReleaseLocks = FALSE;

                AFSAcquireExcl( pVolumeCB->VolumeLock,
                                TRUE);

                InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);

                *VolumeCB = pVolumeCB;

                try_return( ntStatus);
            }

            //
            // Revert our status from the above call back to success.
            //

            ntStatus = STATUS_SUCCESS;
        }

        //
        // For the global root we allocate out volume node and insert it
        // into the volume tree ...
        //

        pVolumeCB = (AFSVolumeCB *)AFSExAllocatePoolWithTag( NonPagedPool,
                                                             sizeof( AFSVolumeCB),
                                                             AFS_VCB_ALLOCATION_TAG);

        if( pVolumeCB == NULL)
        {

            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSInitVolume Failed to allocate the root volume cb\n");

            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
        }

        RtlZeroMemory( pVolumeCB,
                       sizeof( AFSVolumeCB));

        //
        // The non paged portion
        //

        pNonPagedVcb = (AFSNonPagedVolumeCB *)AFSExAllocatePoolWithTag( NonPagedPool,
                                                                        sizeof( AFSNonPagedVolumeCB),
                                                                        AFS_VCB_ALLOCATION_TAG);

        if( pNonPagedVcb == NULL)
        {

            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSInitVolume Failed to allocate the root non paged volume cb\n");

            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
        }

        RtlZeroMemory( pNonPagedVcb,
                       sizeof( AFSNonPagedVolumeCB));

        ExInitializeResourceLite( &pNonPagedVcb->VolumeLock);

        ExInitializeResourceLite( &pNonPagedVcb->ObjectInfoTreeLock);

        pNonPagedObject = (AFSNonPagedObjectInfoCB *)AFSExAllocatePoolWithTag( NonPagedPool,
                                                                               sizeof( AFSNonPagedObjectInfoCB),
                                                                               AFS_VCB_ALLOCATION_TAG);

        if( pNonPagedObject == NULL)
        {

            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSInitVolume Failed to allocate the root non paged object cb\n");

            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
        }

        RtlZeroMemory( pNonPagedObject,
                       sizeof( AFSNonPagedObjectInfoCB));

        ExInitializeResourceLite( &pNonPagedObject->DirectoryNodeHdrLock);

        pVolumeCB->NonPagedVcb = pNonPagedVcb;

        pVolumeCB->ObjectInformation.NonPagedInfo = pNonPagedObject;

        pVolumeCB->VolumeLock = &pNonPagedVcb->VolumeLock;

        pVolumeCB->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock = &pNonPagedObject->DirectoryNodeHdrLock;

        pVolumeCB->ObjectInfoTree.TreeLock = &pNonPagedVcb->ObjectInfoTreeLock;

        //
        // Bias our reference by 1
        //

        AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSInitVolume Initializing count (1) on volume %08lX\n",
                      pVolumeCB);

        pVolumeCB->VolumeReferenceCount = 1;

        AFSAcquireExcl( pVolumeCB->VolumeLock,
                        TRUE);

        pVolumeCB->DirectoryCB = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
                                                                             sizeof( AFSDirectoryCB) + sizeof( WCHAR),
                                                                             AFS_DIR_ENTRY_TAG);

        if( pVolumeCB->DirectoryCB == NULL)
        {

            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
        }

        pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
                                                                                sizeof( AFSNonPagedDirectoryCB),
                                                                                AFS_DIR_ENTRY_NP_TAG);

        if( pNonPagedDirEntry == NULL)
        {

            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
        }

        RtlZeroMemory( pVolumeCB->DirectoryCB,
                       sizeof( AFSDirectoryCB) + sizeof( WCHAR));

        RtlZeroMemory( pNonPagedDirEntry,
                       sizeof( AFSNonPagedDirectoryCB));

        ExInitializeResourceLite( &pNonPagedDirEntry->Lock);

        pVolumeCB->DirectoryCB->NonPaged = pNonPagedDirEntry;

        //
        // Initialize the non-paged portion of the directory entry
        //

        KeQuerySystemTime( &pVolumeCB->ObjectInformation.CreationTime);
        KeQuerySystemTime( &pVolumeCB->ObjectInformation.LastWriteTime);
        KeQuerySystemTime( &pVolumeCB->ObjectInformation.LastAccessTime);

        pVolumeCB->ObjectInformation.FileType = AFS_FILE_TYPE_DIRECTORY;

        SetFlag( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_ROOT_VOLUME);

        pVolumeCB->ObjectInformation.FileId.Cell = RootFid->Cell;
        pVolumeCB->ObjectInformation.FileId.Volume = RootFid->Volume;
        pVolumeCB->ObjectInformation.FileId.Vnode = RootFid->Vnode;
        pVolumeCB->ObjectInformation.FileId.Unique = RootFid->Unique;
        pVolumeCB->ObjectInformation.FileId.Hash = RootFid->Hash;

        pVolumeCB->ObjectInformation.FileAttributes = FILE_ATTRIBUTE_DIRECTORY;

        pVolumeCB->DirectoryCB->NameInformation.FileName.Length = sizeof( WCHAR);

        pVolumeCB->DirectoryCB->NameInformation.FileName.MaximumLength = pVolumeCB->DirectoryCB->NameInformation.FileName.Length;

        pVolumeCB->DirectoryCB->NameInformation.FileName.Buffer = (WCHAR *)((char *)pVolumeCB->DirectoryCB + sizeof( AFSDirectoryCB));

        RtlCopyMemory( pVolumeCB->DirectoryCB->NameInformation.FileName.Buffer,
                       L"\\",
                       sizeof( WCHAR));

        //
        // Copy in the volume information retrieved above
        //

        RtlCopyMemory( &pVolumeCB->VolumeInformation,
                       &stVolumeInformation,
                       sizeof( AFSVolumeInfoCB));

        //
        // Setup pointers
        //

        pVolumeCB->DirectoryCB->ObjectInformation = &pVolumeCB->ObjectInformation;

        pVolumeCB->DirectoryCB->ObjectInformation->VolumeCB = pVolumeCB;

        //
        // Insert the volume into our volume tree. Don't insert any reserved entries
        //

        if( RootFid->Cell != 0)
        {

            pVolumeCB->TreeEntry.HashIndex = ullIndex;

            if( pDeviceExt->Specific.RDR.VolumeTree.TreeHead == NULL)
            {

                pDeviceExt->Specific.RDR.VolumeTree.TreeHead = &pVolumeCB->TreeEntry;

                SetFlag( pVolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE);
            }
            else
            {

                if ( NT_SUCCESS( AFSInsertHashEntry( pDeviceExt->Specific.RDR.VolumeTree.TreeHead,
                                                     &pVolumeCB->TreeEntry)))
                {

                    SetFlag( pVolumeCB->Flags, AFS_VOLUME_INSERTED_HASH_TREE);
                }
            }

            if( pDeviceExt->Specific.RDR.VolumeListHead == NULL)
            {

                pDeviceExt->Specific.RDR.VolumeListHead = pVolumeCB;
            }
            else
            {

                pDeviceExt->Specific.RDR.VolumeListTail->ListEntry.fLink = (void *)pVolumeCB;

                pVolumeCB->ListEntry.bLink = pDeviceExt->Specific.RDR.VolumeListTail;
            }

            pDeviceExt->Specific.RDR.VolumeListTail = pVolumeCB;
        }

        *VolumeCB = pVolumeCB;

try_exit:

        if( !NT_SUCCESS( ntStatus))
        {

            if( pNonPagedVcb != NULL)
            {

                AFSReleaseResource( pVolumeCB->VolumeLock);

                ExDeleteResourceLite( &pNonPagedVcb->VolumeLock);

                ExDeleteResourceLite( &pNonPagedVcb->ObjectInfoTreeLock);

                AFSExFreePool( pNonPagedVcb);
            }

            if( pNonPagedObject != NULL)
            {

                ExDeleteResourceLite( &pNonPagedObject->DirectoryNodeHdrLock);

                AFSExFreePool( pNonPagedObject);
            }

            if( pVolumeCB != NULL)
            {

                if( pVolumeCB->DirectoryCB != NULL)
                {

                    AFSExFreePool( pVolumeCB->DirectoryCB);
                }

                AFSExFreePool( pVolumeCB);
            }

            if( pNonPagedDirEntry != NULL)
            {

                ExDeleteResourceLite( &pNonPagedDirEntry->Lock);

                AFSExFreePool( pNonPagedDirEntry);
            }
        }

        if( bReleaseLocks)
        {

            AFSReleaseResource( pDeviceExt->Specific.RDR.VolumeTree.TreeLock);

            AFSReleaseResource( &pDeviceExt->Specific.RDR.VolumeListLock);
        }
    }

    return ntStatus;
}
Ejemplo n.º 9
0
NTSTATUS
AFSRemoveCcb( IN AFSFcb *Fcb,
              IN AFSCcb *Ccb)
{

    NTSTATUS ntStatus = STATUS_SUCCESS;

    if( Fcb != NULL &&
        BooleanFlagOn( Ccb->Flags, CCB_FLAG_INSERTED_CCB_LIST))
    {

        AFSAcquireExcl( &Fcb->NPFcb->CcbListLock,
                        TRUE);

        if( Ccb->ListEntry.fLink == NULL)
        {

            Fcb->CcbListTail = (AFSCcb *)Ccb->ListEntry.bLink;

            if( Fcb->CcbListTail != NULL)
            {
                Fcb->CcbListTail->ListEntry.fLink = NULL;
            }
        }
        else
        {
            ((AFSCcb *)(Ccb->ListEntry.fLink))->ListEntry.bLink = Ccb->ListEntry.bLink;
        }

        if( Ccb->ListEntry.bLink == NULL)
        {

            Fcb->CcbListHead = (AFSCcb *)Ccb->ListEntry.fLink;

            if( Fcb->CcbListHead != NULL)
            {
                Fcb->CcbListHead->ListEntry.bLink = NULL;
            }
        }
        else
        {
            ((AFSCcb *)(Ccb->ListEntry.bLink))->ListEntry.fLink = Ccb->ListEntry.fLink;
        }

        AFSReleaseResource( &Fcb->NPFcb->CcbListLock);
    }

    if( Ccb->MaskName.Buffer != NULL)
    {

        AFSExFreePool( Ccb->MaskName.Buffer);
    }

    if( BooleanFlagOn( Ccb->Flags, CCB_FLAG_FREE_FULL_PATHNAME))
    {

        AFSExFreePool( Ccb->FullFileName.Buffer);
    }

    //
    // If we have a name array then delete it
    //

    if( Ccb->NameArray != NULL)
    {

        AFSFreeNameArray( Ccb->NameArray);

        Ccb->NameArray = NULL;
    }

    if( Ccb->DirectorySnapshot != NULL)
    {

        AFSExFreePool( Ccb->DirectorySnapshot);

        Ccb->DirectorySnapshot = NULL;
    }

    if( Ccb->NotifyMask.Buffer != NULL)
    {

        AFSExFreePool( Ccb->NotifyMask.Buffer);
    }

    //
    // Free up the Ccb
    //

    AFSExFreePool( Ccb);

    return ntStatus;
}
Ejemplo n.º 10
0
NTSTATUS
AFSFlushBuffers( IN PDEVICE_OBJECT LibDeviceObject,
                 IN PIRP Irp)
{

    UNREFERENCED_PARAMETER(LibDeviceObject);
    AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
    NTSTATUS           ntStatus = STATUS_SUCCESS;
    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
    PFILE_OBJECT       pFileObject = pIrpSp->FileObject;
    AFSFcb            *pFcb = (AFSFcb *)pFileObject->FsContext;
    AFSCcb            *pCcb = (AFSCcb *)pFileObject->FsContext2;
    IO_STATUS_BLOCK    iosb = {0};
    BOOLEAN            bReleaseSectionObject = FALSE;

    pIrpSp = IoGetCurrentIrpStackLocation( Irp);

    __Enter
    {

        if( pFcb == NULL)
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSFlushBuffers Attempted access (%p) when pFcb == NULL\n",
                          Irp));

            try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
        }

        if( pFcb->Header.NodeTypeCode == AFS_ROOT_FCB ||
            pFcb->Header.NodeTypeCode == AFS_ROOT_ALL )
        {

            //
            // Once we support ADS's on directories we need to perform a flush ehre
            //

            try_return( ntStatus = STATUS_SUCCESS);

        }
        else if (pFcb->Header.NodeTypeCode != AFS_FILE_FCB)
        {
            //
            // Nothing to flush Everything but files are write through
            //
            try_return( ntStatus = STATUS_INVALID_PARAMETER);
        }

	AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSFlushBuffers Acquiring Fcb SectionObject lock %p SHARED %08lX\n",
                      &pFcb->NPFcb->SectionObjectResource,
                      PsGetCurrentThread()));

        AFSAcquireShared( &pFcb->NPFcb->SectionObjectResource,
                          TRUE);

        bReleaseSectionObject = TRUE;

        //
        // The flush consists of two parts.  We firstly flush our
        // cache (if we have one), then we tell the service to write
        // to the remote server
        //
        __try
        {

            CcFlushCache( &pFcb->NPFcb->SectionObjectPointers, NULL, 0, &iosb);

            if (!NT_SUCCESS( iosb.Status ))
            {

                AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
                              AFS_TRACE_LEVEL_ERROR,
                              "AFSFlushBuffers CcFlushCache [1] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
                              pFcb->ObjectInformation->FileId.Cell,
                              pFcb->ObjectInformation->FileId.Volume,
                              pFcb->ObjectInformation->FileId.Vnode,
                              pFcb->ObjectInformation->FileId.Unique,
                              iosb.Status,
                              iosb.Information));

                try_return( ntStatus = iosb.Status );
            }
        }
	__except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
        {

            try_return( ntStatus = GetExceptionCode());
        }

	if( !BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
	{

	    AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
			  AFS_TRACE_LEVEL_VERBOSE,
			  "AFSFlushBuffers Releasing Fcb SectionObject lock %p SHARED %08lX\n",
			  &pFcb->NPFcb->SectionObjectResource,
			  PsGetCurrentThread()));

	    AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);

	    bReleaseSectionObject = FALSE;

	    //
	    // Now, flush to the server - if there is stuff to do
	    //

	    ntStatus = AFSFlushExtents( pFcb,
					&pCcb->AuthGroup);

	    if( !NT_SUCCESS( ntStatus))
	    {

		AFSReleaseExtentsWithFlush( pFcb,
					    &pCcb->AuthGroup,
					    TRUE);

		ntStatus = STATUS_SUCCESS;
	    }
	}

try_exit:

        if ( bReleaseSectionObject)
        {

	    AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSFlushBuffers Releasing Fcb SectionObject lock %p SHARED %08lX\n",
                          &pFcb->NPFcb->SectionObjectResource,
                          PsGetCurrentThread()));

            AFSReleaseResource( &pFcb->NPFcb->SectionObjectResource);
        }

        AFSCompleteRequest( Irp, ntStatus);
    }

    return ntStatus;
}
Ejemplo n.º 11
0
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;
}
Ejemplo n.º 12
0
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;
}
Ejemplo n.º 13
0
NTSTATUS
AFSClose( IN PDEVICE_OBJECT LibDeviceObject,
          IN PIRP Irp)
{

    NTSTATUS ntStatus = STATUS_SUCCESS;
    ULONG ulRequestType = 0;
    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
    AFSFcb *pFcb = NULL;
    AFSDeviceExt *pDeviceExt = NULL;
    AFSCcb *pCcb = NULL;
    AFSObjectInfoCB *pObjectInfo = NULL;
    AFSDirectoryCB *pDirCB = NULL;

    __try
    {

        if( AFSRDRDeviceObject == NULL)
        {

            //
            // Let this through, it's an close on the library control device
            //

            try_return( ntStatus);
        }

        pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;

        pIrpSp = IoGetCurrentIrpStackLocation( Irp);

        pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;

        if( pFcb == NULL)
        {
            try_return( ntStatus);
        }

        pObjectInfo = pFcb->ObjectInformation;

        //
        // Perform the close functionality depending on the type of node it is
        //

        switch( pFcb->Header.NodeTypeCode)
        {

            case AFS_IOCTL_FCB:
            {

                AFSPIOCtlOpenCloseRequestCB stPIOCtlClose;
                AFSFileID stParentFileId;

                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSClose Acquiring GlobalRoot lock %08lX EXCL %08lX\n",
                              &pFcb->NPFcb->Resource,
                              PsGetCurrentThread());

                AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                  TRUE);

                pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

                //
                // Send the close to the CM
                //

                RtlZeroMemory( &stPIOCtlClose,
                               sizeof( AFSPIOCtlOpenCloseRequestCB));

                stPIOCtlClose.RequestId = pCcb->RequestID;

                stPIOCtlClose.RootId = pObjectInfo->VolumeCB->ObjectInformation.FileId;

                RtlZeroMemory( &stParentFileId,
                               sizeof( AFSFileID));

                stParentFileId = pObjectInfo->ParentObjectInformation->FileId;

                //
                // Issue the close request to the service
                //

                AFSProcessRequest( AFS_REQUEST_TYPE_PIOCTL_CLOSE,
                                   AFS_REQUEST_FLAG_SYNCHRONOUS,
                                   &pCcb->AuthGroup,
                                   NULL,
                                   &stParentFileId,
                                   (void *)&stPIOCtlClose,
                                   sizeof( AFSPIOCtlOpenCloseRequestCB),
                                   NULL,
                                   NULL);

                pDirCB = pCcb->DirectoryCB;

                //
                // Remove the Ccb and de-allocate it
                //

                ntStatus = AFSRemoveCcb( pFcb,
                                         pCcb);

                if( !NT_SUCCESS( ntStatus))
                {

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                  AFS_TRACE_LEVEL_WARNING,
                                  "AFSClose Failed to remove Ccb from Fcb Status %08lX\n", ntStatus);

                    //
                    // We can't actually fail a close operation so reset the status
                    //

                    ntStatus = STATUS_SUCCESS;
                }

                ASSERT( pDirCB->OpenReferenceCount > 0);

                InterlockedDecrement( &pDirCB->OpenReferenceCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSClose (IOCtl) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
                              &pDirCB->NameInformation.FileName,
                              pDirCB,
                              pCcb,
                              pDirCB->OpenReferenceCount);

                //
                // If this is not the root then decrement the open child reference count
                //

                if( pObjectInfo->ParentObjectInformation != NULL &&
                    pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
                {

                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSClose (IOCtl) Decrement child open ref count on Parent object %08lX Cnt %d\n",
                                  pObjectInfo->ParentObjectInformation,
                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
                }

                AFSReleaseResource( &pFcb->NPFcb->Resource);

                ASSERT( pFcb->OpenReferenceCount != 0);

                InterlockedDecrement( &pFcb->OpenReferenceCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSClose (IOCtl) Decrement count on Fcb %08lX Cnt %d\n",
                              pFcb,
                              pFcb->OpenReferenceCount);

                break;
            }

            case AFS_ROOT_ALL:
            {

                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSClose Acquiring Special Root ALL lock %08lX EXCL %08lX\n",
                              &pFcb->NPFcb->Resource,
                              PsGetCurrentThread());

                AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                TRUE);

                pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

                pDirCB = pCcb->DirectoryCB;

                //
                // Remove the Ccb and de-allocate it
                //

                ntStatus = AFSRemoveCcb( pFcb,
                                         pCcb);

                if( !NT_SUCCESS( ntStatus))
                {

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                  AFS_TRACE_LEVEL_WARNING,
                                  "AFSClose Failed to remove Ccb from Fcb Status %08lX\n", ntStatus);

                    //
                    // We can't actually fail a close operation so reset the status
                    //

                    ntStatus = STATUS_SUCCESS;
                }

                ASSERT( pDirCB->OpenReferenceCount > 0);

                InterlockedDecrement( &pDirCB->OpenReferenceCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSClose Decrement (Root ALL) count on %wZ DE %p Ccb %p Cnt %d\n",
                              &pDirCB->NameInformation.FileName,
                              pDirCB,
                              pCcb,
                              pDirCB->OpenReferenceCount);

                AFSReleaseResource( &pFcb->NPFcb->Resource);

                ASSERT( pFcb->OpenReferenceCount > 0);

                InterlockedDecrement( &pFcb->OpenReferenceCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSClose (RootAll) Decrement count on Fcb %08lX Cnt %d\n",
                              pFcb,
                              pFcb->OpenReferenceCount);

                break;
            }

            //
            // Root, file or directory node
            //

            case AFS_FILE_FCB:
            case AFS_ROOT_FCB:
            case AFS_DIRECTORY_FCB:
            case AFS_SYMBOLIC_LINK_FCB:
            case AFS_MOUNT_POINT_FCB:
            case AFS_DFS_LINK_FCB:
            case AFS_INVALID_FCB:
            {

                pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

                //
                // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
                //

                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSClose Acquiring Dcb lock %08lX EXCL %08lX\n",
                              &pFcb->NPFcb->Resource,
                              PsGetCurrentThread());

                AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                TRUE);

                KeQueryTickCount( &pFcb->ObjectInformation->LastAccessCount);

                pDirCB = pCcb->DirectoryCB;

                //
                // If this entry is deleted then remove the object from the volume tree
                //

                if( BooleanFlagOn( pDirCB->Flags, AFS_DIR_ENTRY_DELETED))
                {

                    if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
                    {

                        //
                        // Stop anything possibly in process
                        //

                        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                                      AFS_TRACE_LEVEL_VERBOSE,
                                      "AFSClose Acquiring Fcb extents lock %08lX EXCL %08lX\n",
                                      &pFcb->NPFcb->Specific.File.ExtentsResource,
                                      PsGetCurrentThread());

                        AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
                                        TRUE);

                        pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;

                        KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
                                    0,
                                    FALSE);

                        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                                      AFS_TRACE_LEVEL_VERBOSE,
                                      "AFSClose Releasing Fcb extents lock %08lX EXCL %08lX\n",
                                      &pFcb->NPFcb->Specific.File.ExtentsResource,
                                      PsGetCurrentThread());

                        AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
                    }

                    AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
                                    TRUE);

                    AFSAcquireExcl( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
                                    TRUE);

                    if ( pDirCB->OpenReferenceCount == 0)
                    {
                        AFSDbgLogMsg( 0,
                                      0,
                                      "AFSClose (Other) OpenReferenceCount is Zero on DE %08lX Ccb %08lX FileName %wZ\n",
                                      pDirCB,
                                      pCcb,
                                      &pDirCB->NameInformation.FileName);
                    }

                    ASSERT( pDirCB->OpenReferenceCount > 0);

                    InterlockedDecrement( &pDirCB->OpenReferenceCount);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSClose (Other) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
                                  &pDirCB->NameInformation.FileName,
                                  pDirCB,
                                  pCcb,
                                  pDirCB->OpenReferenceCount);

                    if( pDirCB->OpenReferenceCount == 0)
                    {

                        AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
                                      AFS_TRACE_LEVEL_VERBOSE,
                                      "AFSClose Deleting dir entry %08lX (%08lX) for %wZ  FID %08lX-%08lX-%08lX-%08lX\n",
                                      pDirCB,
                                      pObjectInfo,
                                      &pDirCB->NameInformation.FileName,
                                      pObjectInfo->FileId.Cell,
                                      pObjectInfo->FileId.Volume,
                                      pObjectInfo->FileId.Vnode,
                                      pObjectInfo->FileId.Unique);

                        //
                        // Remove and delete the directory entry from the parent list
                        //

                        AFSDeleteDirEntry( pObjectInfo->ParentObjectInformation,
                                           pDirCB);

                        if( pObjectInfo->ObjectReferenceCount <= 0)
                        {

                            if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
                            {

                                AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
                                              AFS_TRACE_LEVEL_VERBOSE,
                                              "AFSClose Removing object %08lX from volume tree\n",
                                              pObjectInfo);

                                AFSRemoveHashEntry( &pObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
                                                    &pObjectInfo->TreeEntry);

                                ClearFlag( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
                            }

                            SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DELETED);
                        }
                    }

                    AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);

                    AFSReleaseResource( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
                }
                else
                {

                    ASSERT( pDirCB->OpenReferenceCount > 0);

                    InterlockedDecrement( &pDirCB->OpenReferenceCount);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSClose (Other2) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
                                  &pDirCB->NameInformation.FileName,
                                  pDirCB,
                                  pCcb,
                                  pDirCB->OpenReferenceCount);
                }

                //
                // If this is not the root then decrement the open child reference count
                //

                if( pObjectInfo != NULL &&
                    pObjectInfo->ParentObjectInformation != NULL &&
                    pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
                {

                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSClose Decrement child open ref count on Parent object %08lX Cnt %d\n",
                                  pObjectInfo->ParentObjectInformation,
                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
                }

                if( pFcb->OpenReferenceCount == 1 &&
                    pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
                {

                    SetFlag( pFcb->Flags, AFS_FCB_FILE_CLOSED);

                    //
                    // Attempt to tear down our extent list for the file
                    // If there are remaining dirty extents then attempt to
                    // flush them as well
                    //

                    if( pFcb->Specific.File.ExtentsDirtyCount)
                    {

                        AFSFlushExtents( pFcb,
                                         &pCcb->AuthGroup);
                    }

                    //
                    // Wait for any outstanding queued flushes to complete
                    //

                    AFSWaitOnQueuedFlushes( pFcb);

                    ASSERT( pFcb->Specific.File.ExtentsDirtyCount == 0 &&
                            pFcb->Specific.File.QueuedFlushCount == 0);

                    AFSReleaseResource( &pFcb->NPFcb->Resource);

                    //
                    // Tear 'em down, we'll not be needing them again
                    //

                    AFSTearDownFcbExtents( pFcb,
                                           &pCcb->AuthGroup);
                }
                else
                {

                    if( pFcb->Header.NodeTypeCode == AFS_FILE_FCB &&
                        pFcb->Specific.File.ExtentsDirtyCount &&
                        (pCcb->GrantedAccess & FILE_WRITE_DATA))
                    {

                        AFSFlushExtents( pFcb,
                                         &pCcb->AuthGroup);
                    }

                    AFSReleaseResource( &pFcb->NPFcb->Resource);
                }

                //
                // Remove the Ccb and de-allocate it
                //

                ntStatus = AFSRemoveCcb( pFcb,
                                         pCcb);

                if( !NT_SUCCESS( ntStatus))
                {

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                  AFS_TRACE_LEVEL_WARNING,
                                  "AFSClose Failed to remove Ccb from Fcb Status %08lX\n",
                                  ntStatus);

                    //
                    // We can't actually fail a close operation so reset the status
                    //

                    ntStatus = STATUS_SUCCESS;
                }

                //
                // Decrement the reference count on the Fcb. this is protecting it from teardown.
                //

                ASSERT( pFcb->OpenReferenceCount != 0);

                InterlockedDecrement( &pFcb->OpenReferenceCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSClose Decrement count on Fcb %08lX Cnt %d\n",
                              pFcb,
                              pFcb->OpenReferenceCount);

                break;
            }

            case AFS_SPECIAL_SHARE_FCB:
            {

                AFSPipeOpenCloseRequestCB stPipeClose;

                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSClose Acquiring Special Share lock %08lX EXCL %08lX\n",
                              &pFcb->NPFcb->Resource,
                              PsGetCurrentThread());

                AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                TRUE);

                pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

                pDirCB = pCcb->DirectoryCB;

                RtlZeroMemory( &stPipeClose,
                               sizeof( AFSPipeOpenCloseRequestCB));

                stPipeClose.RequestId = pCcb->RequestID;

                stPipeClose.RootId = pObjectInfo->VolumeCB->ObjectInformation.FileId;

                //
                // Issue the open request to the service
                //

                /*
                AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_CLOSE,
                                   AFS_REQUEST_FLAG_SYNCHRONOUS,
                                   &pFcb->AuthGroup,
                                   &pDirCB->NameInformation.FileName,
                                   NULL,
                                   (void *)&stPipeClose,
                                   sizeof( AFSPipeOpenCloseRequestCB),
                                   NULL,
                                   NULL);
                */

                //
                // Remove the Ccb and de-allocate it
                //

                ntStatus = AFSRemoveCcb( pFcb,
                                         pCcb);

                if( !NT_SUCCESS( ntStatus))
                {

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                  AFS_TRACE_LEVEL_WARNING,
                                  "AFSClose Failed to remove Ccb from Fcb Status %08lX\n", ntStatus);

                    //
                    // We can't actually fail a close operation so reset the status
                    //

                    ntStatus = STATUS_SUCCESS;
                }

                ASSERT( pDirCB->OpenReferenceCount > 0);

                InterlockedDecrement( &pDirCB->OpenReferenceCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSClose (Share) Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
                              &pDirCB->NameInformation.FileName,
                              pDirCB,
                              pCcb,
                              pDirCB->OpenReferenceCount);

                //
                // If this is not the root then decrement the open child reference count
                //

                if( pObjectInfo->ParentObjectInformation != NULL &&
                    pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
                {

                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSClose (Share) Decrement child open ref count on Parent object %08lX Cnt %d\n",
                                  pObjectInfo->ParentObjectInformation,
                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenReferenceCount);
                }

                AFSReleaseResource( &pFcb->NPFcb->Resource);

                ASSERT( pFcb->OpenReferenceCount != 0);

                InterlockedDecrement( &pFcb->OpenReferenceCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSClose (Share) Decrement count on Fcb %08lX Cnt %d\n",
                              pFcb,
                              pFcb->OpenReferenceCount);

                break;
            }

            default:

                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_ERROR,
                              "AFSClose Processing unknown node type %d\n",
                              pFcb->Header.NodeTypeCode);

                break;
        }

try_exit:

        //
        // Complete the request
        //

        AFSCompleteRequest( Irp,
                            ntStatus);
    }
    __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
    {

        AFSDbgLogMsg( 0,
                      0,
                      "EXCEPTION - AFSClose\n");

        AFSDumpTraceFilesFnc();
    }

    return ntStatus;
}
Ejemplo n.º 14
0
NTSTATUS
AFSProcessUserFsRequest( IN PIRP Irp)
{

    NTSTATUS ntStatus = STATUS_SUCCESS;
    ULONG ulFsControlCode;
    AFSFcb *pFcb = NULL;
    PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp );
    AFSCcb *pCcb = NULL;
    ULONG ulOutputBufferLen, ulInputBufferLen;

    __Enter
    {

        ulFsControlCode = pIrpSp->Parameters.FileSystemControl.FsControlCode;

        pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;

        pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

        if( pFcb == NULL ||
            pCcb == NULL ||
            pCcb->DirectoryCB == NULL)
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_VERBOSE_2,
                          "AFSProcessUserFsRequest Invalid Fcb\n"));

            try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
        }

        if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
        {

            ntStatus = AFSProcessShareFsCtrl( Irp,
                                              pFcb,
                                              pCcb);

            try_return( ntStatus);
        }

        ulOutputBufferLen = pIrpSp->Parameters.FileSystemControl.OutputBufferLength;
        ulInputBufferLen = pIrpSp->Parameters.FileSystemControl.InputBufferLength;

        //
        // Process the request
        //

        switch( ulFsControlCode )
        {

            case FSCTL_REQUEST_OPLOCK_LEVEL_1:
            case FSCTL_REQUEST_OPLOCK_LEVEL_2:
            case FSCTL_REQUEST_BATCH_OPLOCK:
            case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE:
            case FSCTL_OPBATCH_ACK_CLOSE_PENDING:
            case FSCTL_OPLOCK_BREAK_NOTIFY:
            case FSCTL_OPLOCK_BREAK_ACK_NO_2:
            case FSCTL_REQUEST_FILTER_OPLOCK :
            {
                //
                // Note that implementing this call will probably need us
                // to call the server as well as adding code in read and
                // write and caching.  Also that it is unlikely that
                // anyone will ever call us at this point - RDR doesn't
                // allow it
                //

                ntStatus = STATUS_NOT_IMPLEMENTED;

                break;
            }

            case FSCTL_LOCK_VOLUME:
            {
                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing FSCTL_LOCK_VOLUME request\n"));

                ntStatus = STATUS_NOT_IMPLEMENTED;

                break;
            }

            case FSCTL_UNLOCK_VOLUME:
            {
                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing FSCTL_UNLOCK_VOLUME request\n"));

                ntStatus = STATUS_NOT_IMPLEMENTED;

                break;
            }

            case FSCTL_DISMOUNT_VOLUME:
            {
                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing FSCTL_DISMOUNT_VOLUME request\n"));

                ntStatus = STATUS_NOT_IMPLEMENTED;

                break;
            }

            case FSCTL_MARK_VOLUME_DIRTY:
            {
                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing FSCTL_MARK_VOLUME_DIRTY request\n"));

                ntStatus = STATUS_NOT_IMPLEMENTED;

                break;
            }

            case FSCTL_IS_VOLUME_DIRTY:
            {
                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing FSCTL_IS_VOLUME_DIRTY request\n"));

                ntStatus = STATUS_NOT_IMPLEMENTED;

                break;
            }

            case FSCTL_IS_VOLUME_MOUNTED:
            {
                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing FSCTL_IS_VOLUME_MOUNTED request\n"));

                ntStatus = STATUS_NOT_IMPLEMENTED;

                break;
            }

            case FSCTL_IS_PATHNAME_VALID:
            {
                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing FSCTL_IS_PATHNAME_VALID request\n"));

                ntStatus = STATUS_SUCCESS;

                break;
            }

#ifndef FSCTL_CSC_INTERNAL
#define FSCTL_CSC_INTERNAL                  CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 107, METHOD_NEITHER, FILE_ANY_ACCESS)
#endif
            case FSCTL_CSC_INTERNAL:
            {
                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing FSCTL_CSC_INTERNAL request\n"));

                ntStatus = STATUS_INVALID_DEVICE_REQUEST;

                break;
            }

            case FSCTL_GET_REPARSE_POINT:
            {

                REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
                REPARSE_DATA_BUFFER *pMSFTReparseBuffer = (REPARSE_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
                ULONG ulRemainingLen = ulOutputBufferLen;
                AFSReparseTagInfo *pReparseInfo = NULL;
                BOOLEAN bRelative = FALSE;
                BOOLEAN bDriveLetter = FALSE;
                WCHAR * PathBuffer = NULL;

                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing FSCTL_GET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n",
                              &pCcb->DirectoryCB->NameInformation.FileName,
                              pFcb->ObjectInformation->FileType,
                              pFcb->ObjectInformation->FileAttributes));

                //
                // Check if we have the reparse entry set on the entry
                //

                if( !BooleanFlagOn( pFcb->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
                {

                    ntStatus = STATUS_NOT_A_REPARSE_POINT;

                    break;
                }


                switch ( pFcb->ObjectInformation->FileType) {
                case AFS_FILE_TYPE_MOUNTPOINT:

                    if( ulOutputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
                    {

                        ntStatus = STATUS_BUFFER_TOO_SMALL;

                        Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer);

                        break;
                    }

                    ulRemainingLen -= FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer);

                    break;

                default:

                    if( ulOutputBufferLen < FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
                    {

                        ntStatus = STATUS_BUFFER_TOO_SMALL;

                        Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer);

                        break;
                    }

                    ulRemainingLen -= FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer);

                    break;
                }

                //
                // Populate the data in the reparse buffer
                //

                pReparseBuffer->ReparseDataLength  = 0;

                AFSAcquireExcl( &pCcb->DirectoryCB->NonPaged->Lock,
                                TRUE);

                if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
                {

                    //
                    // We'll reset the DV to ensure we validate the metadata content
                    //

                    pFcb->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;

                    SetFlag( pFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);

                    AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSProcessUserFsRequest Verifying symlink %wZ FID %08lX-%08lX-%08lX-%08lX\n",
                                  &pCcb->DirectoryCB->NameInformation.FileName,
                                  pFcb->ObjectInformation->FileId.Cell,
                                  pFcb->ObjectInformation->FileId.Volume,
                                  pFcb->ObjectInformation->FileId.Vnode,
                                  pFcb->ObjectInformation->FileId.Unique));

                    ntStatus = AFSVerifyEntry( &pCcb->AuthGroup,
					       pCcb->DirectoryCB,
					       FALSE);

                    if( !NT_SUCCESS( ntStatus))
                    {

                        AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                                      AFS_TRACE_LEVEL_ERROR,
                                      "AFSProcessUserFsRequest Failed to verify symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
                                      &pCcb->DirectoryCB->NameInformation.FileName,
                                      pFcb->ObjectInformation->FileId.Cell,
                                      pFcb->ObjectInformation->FileId.Volume,
                                      pFcb->ObjectInformation->FileId.Vnode,
                                      pFcb->ObjectInformation->FileId.Unique,
                                      ntStatus));

                        AFSReleaseResource( &pCcb->DirectoryCB->NonPaged->Lock);

                        break;
                    }
                }

                pReparseInfo = (AFSReparseTagInfo *)&pReparseBuffer->GenericReparseBuffer.DataBuffer[ 0];

                switch( pFcb->ObjectInformation->FileType)
                {

                    case AFS_FILE_TYPE_SYMLINK:
                    {

                        if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
                        {

                            ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;

                            break;
                        }

                        bRelative = AFSIsRelativeName( &pCcb->DirectoryCB->NameInformation.TargetName);

                        if ( bRelative)
                        {

                            if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
                                pCcb->DirectoryCB->NameInformation.TargetName.Length)
                            {

                                ntStatus = STATUS_BUFFER_TOO_SMALL;

                                Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
                                    pCcb->DirectoryCB->NameInformation.TargetName.Length;

                                break;
                            }

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = SYMLINK_FLAG_RELATIVE;

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength =
                                pCcb->DirectoryCB->NameInformation.TargetName.Length;

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength =
                                pCcb->DirectoryCB->NameInformation.TargetName.Length;

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0;

                            PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer;

                            RtlCopyMemory( PathBuffer,
                                           pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
                                           pCcb->DirectoryCB->NameInformation.TargetName.Length);

                            pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) -
                                FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
                                pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
                        }
                        else
                        {

                            if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
                                /* Display Name */
                                pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR) +
                                /* Substitute Name */
                                pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR))
                            {

                                ntStatus = STATUS_BUFFER_TOO_SMALL;

                                Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
                                    pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR) +
                                    pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR);

                                break;
                            }

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = 0;

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength =
                                pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR);

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength =
                                pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR);

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset =
                                pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength;

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0;

                            PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer;

                            /* Display Name */
                            *PathBuffer++ = L'\\';

                            RtlCopyMemory( PathBuffer,
                                           pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
                                           pCcb->DirectoryCB->NameInformation.TargetName.Length);

                            PathBuffer += pCcb->DirectoryCB->NameInformation.TargetName.Length / sizeof( WCHAR);

                            /* Substitute Name */
                            *PathBuffer++ = L'\\';
                            *PathBuffer++ = L'?';
                            *PathBuffer++ = L'?';
                            *PathBuffer++ = L'\\';
                            *PathBuffer++ = L'U';
                            *PathBuffer++ = L'N';
                            *PathBuffer++ = L'C';

                            RtlCopyMemory( PathBuffer,
                                           pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
                                           pCcb->DirectoryCB->NameInformation.TargetName.Length);

                            pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) -
                                FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
                                pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength +
                                pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
                        }

                        break;
                    }

                    case AFS_FILE_TYPE_MOUNTPOINT:
                    {
                        UNICODE_STRING Cell, Volume;
                        USHORT Type;

                        if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
                        {
                            ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;

                            break;
                        }

                        if ( !AFSParseMountPointTarget( &pCcb->DirectoryCB->NameInformation.TargetName,
                                                        &Type,
                                                        &Volume,
                                                        &Cell))
                        {
                            ntStatus = STATUS_INVALID_PARAMETER;

                            break;
                        }

                        if( ulRemainingLen < (ULONG) FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) + Volume.Length + Cell.Length)
                        {

                            ntStatus = STATUS_BUFFER_TOO_SMALL;

                            Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
                                                        FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) +
                                                        Volume.Length + Cell.Length;

                            break;
                        }

                        pReparseInfo->SubTag = OPENAFS_SUBTAG_MOUNTPOINT;

                        pReparseInfo->AFSMountPoint.Type = Type;

                        pReparseInfo->AFSMountPoint.MountPointCellLength = Cell.Length;

                        pReparseInfo->AFSMountPoint.MountPointVolumeLength = Volume.Length;

                        RtlCopyMemory( pReparseInfo->AFSMountPoint.Buffer,
                                       Cell.Buffer,
                                       Cell.Length);

                        RtlCopyMemory( &pReparseInfo->AFSMountPoint.Buffer[ Cell.Length / sizeof( WCHAR)],
                                       Volume.Buffer,
                                       Volume.Length);

                        pReparseBuffer->ReparseDataLength = (FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) + Volume.Length + Cell.Length);

                        break;
                    }

                    case AFS_FILE_TYPE_DFSLINK:
                    {

                        if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
                        {

                            ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;

                            break;
                        }

                        bRelative = ( pCcb->DirectoryCB->NameInformation.TargetName.Buffer[0] == L'\\');

                        bDriveLetter = (bRelative == FALSE && pCcb->DirectoryCB->NameInformation.TargetName.Buffer[1] == L':');

                        if ( bRelative)
                        {

                            if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
                                pCcb->DirectoryCB->NameInformation.TargetName.Length)
                            {

                                ntStatus = STATUS_BUFFER_TOO_SMALL;

                                Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
                                    pCcb->DirectoryCB->NameInformation.TargetName.Length;

                                break;
                            }

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = SYMLINK_FLAG_RELATIVE;

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength =
                                pCcb->DirectoryCB->NameInformation.TargetName.Length;

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength =
                                pCcb->DirectoryCB->NameInformation.TargetName.Length;

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0;

                            PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer;

                            RtlCopyMemory( PathBuffer,
                                           pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
                                           pCcb->DirectoryCB->NameInformation.TargetName.Length);

                            pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) -
                                FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
                                pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
                        }
                        else if ( bDriveLetter)
                        {

                            if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
                                /* Display Name */
                                pCcb->DirectoryCB->NameInformation.TargetName.Length +
                                /* Substitute Name */
                                pCcb->DirectoryCB->NameInformation.TargetName.Length + 4 * sizeof( WCHAR))
                            {

                                ntStatus = STATUS_BUFFER_TOO_SMALL;

                                Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
                                    pCcb->DirectoryCB->NameInformation.TargetName.Length +
                                    pCcb->DirectoryCB->NameInformation.TargetName.Length + 4 * sizeof( WCHAR);

                                break;
                            }

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = 0;

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength =
                                pCcb->DirectoryCB->NameInformation.TargetName.Length + 4 * sizeof( WCHAR);

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength =
                                pCcb->DirectoryCB->NameInformation.TargetName.Length;

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset =
                                pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength;

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0;

                            PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer;

                            /* Display Name */
                            RtlCopyMemory( PathBuffer,
                                           pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
                                           pCcb->DirectoryCB->NameInformation.TargetName.Length);

                            PathBuffer += pCcb->DirectoryCB->NameInformation.TargetName.Length / sizeof( WCHAR);

                            /* Substitute Name */
                            *PathBuffer++ = L'\\';
                            *PathBuffer++ = L'?';
                            *PathBuffer++ = L'?';
                            *PathBuffer++ = L'\\';

                            RtlCopyMemory( PathBuffer,
                                           pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
                                           pCcb->DirectoryCB->NameInformation.TargetName.Length);

                            pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) -
                                FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
                                pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength +
                                pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
                        }
                        else
                        {

                            if( ulRemainingLen < (ULONG) FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
                                /* Display Name */
                                pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR) +
                                /* Substitute Name */
                                pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR))
                            {

                                ntStatus = STATUS_BUFFER_TOO_SMALL;

                                Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
                                    pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR) +
                                    pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR);

                                break;
                            }

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.Flags = 0;

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength =
                                pCcb->DirectoryCB->NameInformation.TargetName.Length + 7 * sizeof( WCHAR);

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength =
                                pCcb->DirectoryCB->NameInformation.TargetName.Length + 1 * sizeof( WCHAR);

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset =
                                pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength;

                            pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset = 0;

                            PathBuffer = pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer;

                            /* Display Name */
                            *PathBuffer++ = L'\\';

                            RtlCopyMemory( PathBuffer,
                                           pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
                                           pCcb->DirectoryCB->NameInformation.TargetName.Length);

                            PathBuffer += pCcb->DirectoryCB->NameInformation.TargetName.Length / sizeof( WCHAR);

                            /* Substitute Name */
                            *PathBuffer++ = L'\\';
                            *PathBuffer++ = L'?';
                            *PathBuffer++ = L'?';
                            *PathBuffer++ = L'\\';
                            *PathBuffer++ = L'U';
                            *PathBuffer++ = L'N';
                            *PathBuffer++ = L'C';

                            RtlCopyMemory( PathBuffer,
                                           pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
                                           pCcb->DirectoryCB->NameInformation.TargetName.Length);

                            pReparseBuffer->ReparseDataLength = FIELD_OFFSET( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) -
                                FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
                                pMSFTReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength +
                                pMSFTReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
                        }

                        break;
                    }

                    default:

                        ntStatus = STATUS_NOT_A_REPARSE_POINT;

                        break;
                }

                if ( ntStatus == STATUS_SUCCESS)
                {

                    ulRemainingLen -= pReparseBuffer->ReparseDataLength;

                    if ( pFcb->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT)
                    {

                        pReparseBuffer->ReparseTag = IO_REPARSE_TAG_SURROGATE|IO_REPARSE_TAG_OPENAFS_DFS;

                        RtlCopyMemory( &pReparseBuffer->ReparseGuid,
                                       &GUID_AFS_REPARSE_GUID,
                                       sizeof( GUID));

                        Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer)
                            + pReparseBuffer->ReparseDataLength;
                    }
                    else
                    {

                        pReparseBuffer->ReparseTag = IO_REPARSE_TAG_SYMLINK;

                        Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer)
                            + pReparseBuffer->ReparseDataLength;
                    }
                }

                AFSReleaseResource( &pCcb->DirectoryCB->NonPaged->Lock);

                break;
            }

            case FSCTL_SET_REPARSE_POINT:
            {

                REPARSE_GUID_DATA_BUFFER *pReparseGUIDBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
                REPARSE_DATA_BUFFER *pReparseBuffer = NULL;
                AFSReparseTagInfo *pReparseInfo = NULL;
                AFSObjectInfoCB *pParentObjectInfo = NULL;
                UNICODE_STRING uniTargetName;
                ULONGLONG ullIndex = 0;
                LONG lCount;

                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSProcessUserFsRequest Processing FSCTL_SET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n",
                              &pCcb->DirectoryCB->NameInformation.FileName,
                              pFcb->ObjectInformation->FileType,
                              pFcb->ObjectInformation->FileAttributes));

                if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
                {

                    ntStatus = STATUS_IO_REPARSE_DATA_INVALID;

                    break;
                }

                if( (pReparseGUIDBuffer->ReparseTag & 0x0000FFFF) == IO_REPARSE_TAG_OPENAFS_DFS)
                {

                    if( RtlCompareMemory( &pReparseGUIDBuffer->ReparseGuid,
                                          &GUID_AFS_REPARSE_GUID,
                                          sizeof( GUID)) != sizeof( GUID))
                    {

                        ntStatus = STATUS_REPARSE_ATTRIBUTE_CONFLICT;

                        break;
                    }

                    if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
                                                                        sizeof( AFSReparseTagInfo))
                    {

                        ntStatus = STATUS_IO_REPARSE_DATA_INVALID;

                        break;
                    }

                    pReparseInfo = (AFSReparseTagInfo *)pReparseGUIDBuffer->GenericReparseBuffer.DataBuffer;

                    switch( pReparseInfo->SubTag)
                    {

                        case OPENAFS_SUBTAG_SYMLINK:
                        {

                            if( ulInputBufferLen < (ULONG)(FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
                                                           FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) +
                                                           pReparseInfo->AFSSymLink.SymLinkTargetLength))
                            {

                                ntStatus = STATUS_IO_REPARSE_DATA_INVALID;

                                break;
                            }

                            uniTargetName.Length = pReparseInfo->AFSSymLink.SymLinkTargetLength;
                            uniTargetName.MaximumLength = uniTargetName.Length;

                            uniTargetName.Buffer = (WCHAR *)pReparseInfo->AFSSymLink.Buffer;

                            break;
                        }

                        case OPENAFS_SUBTAG_UNC:
                        {

                            if( ulInputBufferLen < (ULONG)(FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
                                                           FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) +
                                                           pReparseInfo->UNCReferral.UNCTargetLength))
                            {

                                ntStatus = STATUS_IO_REPARSE_DATA_INVALID;

                                break;
                            }

                            uniTargetName.Length = pReparseInfo->UNCReferral.UNCTargetLength;
                            uniTargetName.MaximumLength = uniTargetName.Length;

                            uniTargetName.Buffer = (WCHAR *)pReparseInfo->UNCReferral.Buffer;

                            break;
                        }

                        case OPENAFS_SUBTAG_MOUNTPOINT:
                            //
                            // Not yet handled
                            //
                        default:
                        {

                            ntStatus = STATUS_IO_REPARSE_DATA_INVALID;

                            break;
                        }
                    }
                }
                else
                {
                    //
                    // Handle Microsoft Reparse Tags
                    //

                    switch( pReparseGUIDBuffer->ReparseTag)
                    {

                        case IO_REPARSE_TAG_MOUNT_POINT:
                        {

                            pReparseBuffer = (REPARSE_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;

                            uniTargetName.Length = pReparseBuffer->MountPointReparseBuffer.PrintNameLength;
                            uniTargetName.MaximumLength = uniTargetName.Length;

                            uniTargetName.Buffer = (WCHAR *)((char *)pReparseBuffer->MountPointReparseBuffer.PathBuffer +
                                                              pReparseBuffer->MountPointReparseBuffer.PrintNameOffset);

                            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                                          AFS_TRACE_LEVEL_VERBOSE_2,
                                          "AFSProcessUserFsRequest IO_REPARSE_TAG_MOUNT_POINT request %wZ\n",
                                          &uniTargetName));

                            ntStatus = STATUS_IO_REPARSE_DATA_INVALID;

                            break;
                        }

                        case IO_REPARSE_TAG_SYMLINK:
                        {

                            pReparseBuffer = (REPARSE_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;

                            uniTargetName.Length = pReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
                            uniTargetName.MaximumLength = uniTargetName.Length;

                            uniTargetName.Buffer = (WCHAR *)((char *)pReparseBuffer->SymbolicLinkReparseBuffer.PathBuffer +
                                                              pReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset);

                            AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                                          AFS_TRACE_LEVEL_VERBOSE_2,
                                          "AFSProcessUserFsRequest IO_REPARSE_TAG_SYMLINK request %wZ\n",
                                          &uniTargetName));
                            break;
                        }

                        default:
                        {

                            ntStatus = STATUS_IO_REPARSE_DATA_INVALID;

                            break;
                        }
                    }
                }

                if( !NT_SUCCESS( ntStatus))
                {

                    break;
                }

                //
                // First thing is to locate/create our object information block
                // for this entry
                //

                AFSAcquireExcl( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock,
                                TRUE);

                if ( AFSIsVolumeFID( &pFcb->ObjectInformation->ParentFileId))
                {

                    pParentObjectInfo = &pFcb->ObjectInformation->VolumeCB->ObjectInformation;
                }
                else
                {
                    ullIndex = AFSCreateLowIndex( &pFcb->ObjectInformation->ParentFileId);

                    ntStatus = AFSLocateHashEntry( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeHead,
                                                   ullIndex,
                                                   (AFSBTreeEntry **)&pParentObjectInfo);
                }

                if ( NT_SUCCESS( ntStatus))
                {

                    lCount = AFSObjectInfoIncrement( pParentObjectInfo,
                                                     AFS_OBJECT_REFERENCE_FS_REQ);

                    AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSProcessUserFsRequest Increment count on object %p Cnt %d\n",
                                  pParentObjectInfo,
                                  lCount));

                    KeQueryTickCount( &pParentObjectInfo->LastAccessCount);
                }

                AFSReleaseResource( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock);

                if ( NT_SUCCESS( ntStatus))
                {

                    //
                    // Extract out the information to the call to the service
                    //

                    ntStatus = AFSCreateSymlink( &pCcb->AuthGroup,
                                                 pParentObjectInfo,
                                                 &pCcb->DirectoryCB->NameInformation.FileName,
                                                 pFcb->ObjectInformation,
                                                 &uniTargetName);

                    AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                                  AFS_TRACE_LEVEL_VERBOSE_2,
                                  "AFSProcessUserFsRequest Processed FSCTL_SET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x Status %08lX\n",
                                  &pCcb->DirectoryCB->NameInformation.FileName,
                                  pFcb->ObjectInformation->FileType,
                                  pFcb->ObjectInformation->FileAttributes,
                                  ntStatus));

                    AFSAcquireShared( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock,
                                      TRUE);

                    lCount = AFSObjectInfoDecrement( pParentObjectInfo,
                                                     AFS_OBJECT_REFERENCE_FS_REQ);

                    AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSProcessUserFsRequest Decrement count on object %p Cnt %d\n",
                                  pParentObjectInfo,
                                  lCount));

                    AFSReleaseResource( pFcb->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock);
                }

                break;
            }

            case FSCTL_DELETE_REPARSE_POINT:
            {

                REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;

                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing FSCTL_DELETE_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n",
                              &pCcb->DirectoryCB->NameInformation.FileName,
                              pFcb->ObjectInformation->FileType,
                              pFcb->ObjectInformation->FileAttributes));

                //
                // Check if we have the reparse entry set on the entry
                //

                if( !BooleanFlagOn( pFcb->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
                {

                    ntStatus = STATUS_NOT_A_REPARSE_POINT;

                    break;
                }

                if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
                {

                    ntStatus = STATUS_INVALID_PARAMETER;

                    break;
                }

                if( (pReparseBuffer->ReparseTag & 0x0000FFFF) != IO_REPARSE_TAG_OPENAFS_DFS)
                {

                    ntStatus = STATUS_IO_REPARSE_TAG_MISMATCH;

                    break;
                }

                if( RtlCompareMemory( &pReparseBuffer->ReparseGuid,
                                      &GUID_AFS_REPARSE_GUID,
                                      sizeof( GUID)) != sizeof( GUID))
                {

                    ntStatus = STATUS_REPARSE_ATTRIBUTE_CONFLICT;

                    break;
                }

                //
                // Claim success.  The typical usage is setting delete on close
                // as the next operation on the reparse point before closing
                // the handle.
                //

                ntStatus = STATUS_SUCCESS;

                break;
            }

#ifndef FSCTL_SET_PURGE_FAILURE_MODE
#define FSCTL_SET_PURGE_FAILURE_MODE        CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 156, METHOD_BUFFERED, FILE_ANY_ACCESS)
#endif

            case FSCTL_SET_PURGE_FAILURE_MODE:
            {

                //
                // For the time being just succeed this call
                //

                ntStatus = STATUS_SUCCESS;

                break;
            }

            default :
            {

                AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing default (%08lX) request\n",
                              ulFsControlCode));

                ntStatus = STATUS_INVALID_DEVICE_REQUEST;

                break;
            }
        }

try_exit:

        NOTHING;
    }

    return ntStatus;
}
Ejemplo n.º 15
0
void
AFSProcessCreate( IN HANDLE ParentId,
                  IN HANDLE ProcessId,
                  IN HANDLE CreatingProcessId,
                  IN HANDLE CreatingThreadId)
{
    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
    AFSProcessCB *pProcessCB = NULL;

    __Enter
    {

        AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSProcessCreate Acquiring Control ProcessTree.TreeLock lock %p EXCL %08lX\n",
                      pDeviceExt->Specific.Control.ProcessTree.TreeLock,
                      PsGetCurrentThread()));

        AFSAcquireExcl( pDeviceExt->Specific.Control.ProcessTree.TreeLock,
                        TRUE);

        AFSDbgTrace(( AFS_SUBSYSTEM_PROCESS_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSProcessCreate Parent %08lX Process %08lX %08lX\n",
                      ParentId,
                      ProcessId,
                      PsGetCurrentThread()));

        pProcessCB = AFSInitializeProcessCB( (ULONGLONG)ParentId,
                                             (ULONGLONG)ProcessId);

        if( pProcessCB != NULL)
        {

            pProcessCB->CreatingProcessId = (ULONGLONG)CreatingProcessId;

            pProcessCB->CreatingThreadId = (ULONGLONG)CreatingThreadId;

            //
            // Now assign the AuthGroup ACE
            //

            AFSValidateProcessEntry( ProcessId,
                                     TRUE);
        }
        else
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_PROCESS_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSProcessCreate Initialization failure for Parent %08lX Process %08lX %08lX\n",
                          ParentId,
                          ProcessId,
                          PsGetCurrentThread()));
        }

        AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock);
    }

    return;
}
Ejemplo n.º 16
0
GUID *
AFSValidateProcessEntry( IN HANDLE  ProcessId,
                         IN BOOLEAN bProcessTreeLocked)
{

    GUID *pAuthGroup = NULL;
    NTSTATUS ntStatus = STATUS_SUCCESS;
    AFSProcessCB *pProcessCB = NULL, *pParentProcessCB = NULL;
    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
    ULONGLONG ullProcessID = (ULONGLONG)ProcessId;
    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
    {

        uniSIDString.Length = 0;
        uniSIDString.MaximumLength = 0;
        uniSIDString.Buffer = NULL;

        if ( !bProcessTreeLocked)
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "AFSValidateProcessEntry Acquiring Control ProcessTree.TreeLock lock %p SHARED %08lX\n",
                          pDeviceExt->Specific.Control.ProcessTree.TreeLock,
                          PsGetCurrentThread()));

            AFSAcquireShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock,
                              TRUE);
        }

        AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "%s Entry for ProcessID %I64X\n",
                      __FUNCTION__,
                      ullProcessID));

        ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead,
                                       ullProcessID,
                                       (AFSBTreeEntry **)&pProcessCB);

        if( !NT_SUCCESS( ntStatus) ||
            pProcessCB == NULL)
        {

            if ( !bProcessTreeLocked)
            {

                AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock);

                AFSAcquireExcl( pDeviceExt->Specific.Control.ProcessTree.TreeLock,
                                TRUE);
            }

            ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead,
                                           ullProcessID,
                                           (AFSBTreeEntry **)&pProcessCB);

            if( !NT_SUCCESS( ntStatus) ||
                pProcessCB == NULL)
            {

                AFSProcessCreate( 0,
                                  ProcessId,
                                  0,
                                  0);
            }

            if( !NT_SUCCESS( ntStatus) ||
                pProcessCB == NULL)
            {

                AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
                              AFS_TRACE_LEVEL_ERROR,
                              "%s Failed to locate process entry for ProcessID %I64X\n",
                              __FUNCTION__,
                              ullProcessID));

                try_return( ntStatus = STATUS_UNSUCCESSFUL);
            }

            if ( !bProcessTreeLocked)
            {

                AFSConvertToShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock);
            }
        }

        //
        // Locate and lock the ParentProcessCB if we have one
        //

        if( pProcessCB->ParentProcessId != 0)
        {

            AFSDbgTrace(( 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);

                AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "%s Located process entry for Parent ProcessID %I64X\n",
                              __FUNCTION__,
                              pProcessCB->ParentProcessId));
            }
        }
        else
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "%s No parent ID for ProcessID %I64X\n",
                          __FUNCTION__,
                          ullProcessID));
        }

        AFSAcquireExcl( &pProcessCB->Lock,
                        TRUE);

#if defined(_WIN64)

        //
        // Mark the process as 64-bit if it is.
        //

        if( !IoIs32bitProcess( NULL))
        {

            SetFlag( pProcessCB->Flags, AFS_PROCESS_FLAG_IS_64BIT);
        }
        else
        {

            ClearFlag( pProcessCB->Flags, AFS_PROCESS_FLAG_IS_64BIT);
        }
#endif

        //
        // Locate the SID for the caller
        //

        ntStatus = AFSGetCallerSID( &uniSIDString, &bImpersonation);

        if( !NT_SUCCESS( ntStatus))
        {

            AFSDbgTrace(( 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)
        {

            AFSDbgTrace(( 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);
        }

        AFSDbgTrace(( 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);

                AFSDbgTrace(( 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->CreatingThreadId)
                    {
                        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);

                    AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "%s PID %I64X 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);

                    AFSDbgTrace(( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "%s PID %I64X 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);

                    AFSDbgTrace(( 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))
        {

            AFSDbgTrace(( 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);

                AFSDbgTrace(( 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);

        AFSDbgTrace(( 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);

            AFSDbgTrace(( 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);

        AFSDbgTrace(( 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);
        }

        if ( !bProcessTreeLocked)
        {

            AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock);
        }
    }

    return pAuthGroup;
}
Ejemplo n.º 17
0
void
AFSProcessDestroy( IN HANDLE ProcessId)
{

    NTSTATUS ntStatus = STATUS_SUCCESS;
    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
    AFSProcessCB *pProcessCB = NULL;
    AFSProcessAuthGroupCB *pProcessAuthGroup = NULL, *pLastAuthGroup = NULL;
    AFSThreadCB *pThreadCB = NULL, *pNextThreadCB = NULL;

    __Enter
    {

        AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSProcessDestroy Acquiring Control ProcessTree.TreeLock lock %p EXCL %08lX\n",
                      pDeviceExt->Specific.Control.ProcessTree.TreeLock,
                      PsGetCurrentThreadId()));

        AFSAcquireExcl( pDeviceExt->Specific.Control.ProcessTree.TreeLock,
                        TRUE);
        //
        // It's a remove so pull the entry
        //

        AFSDbgTrace(( AFS_SUBSYSTEM_PROCESS_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSProcessDestroy 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
        {
            AFSDbgTrace(( AFS_SUBSYSTEM_PROCESS_PROCESSING,
                          AFS_TRACE_LEVEL_WARNING,
                          "AFSProcessDestroy Process %08lX not found in ProcessTree Status %08lX %08lX\n",
                          ProcessId,
                          ntStatus,
                          PsGetCurrentThread()));
        }

        AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock);
    }

    return;
}
Ejemplo n.º 18
0
NTSTATUS
AFSProcessQueuedResults( IN BOOLEAN CancelRequest)
{

    NTSTATUS ntStatus = STATUS_SUCCESS;
    AFSLibraryQueueRequestCB *pRequest = NULL;
    AFSDeviceExt       *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;

    __Enter
    {

        AFSDbgTrace(( 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;

                AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "%s Cancelling request Irp %p\n",
                              __FUNCTION__,
                              pRequest->Irp));

                IoCompleteRequest( pRequest->Irp,
                                   IO_NO_INCREMENT);
            }
            else
            {

                AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "%s Resubmitting request Irp %p\n",
                              __FUNCTION__,
                              pRequest->Irp));

                AFSSubmitLibraryRequest( pRequest->Irp);
            }

            ExFreePool( pRequest);
        }

        AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "%s Completed\n",
                      __FUNCTION__));
    }

    return ntStatus;
}
Ejemplo n.º 19
0
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;
}
Ejemplo n.º 20
0
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;
    PVOID            Objects[2];

    __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;
        }

        //
        // Populate the objects array for the non release only threads
        // Release only workers can only process release extent events
        // whereas normal workers can process any kind of event.
        // Release only workers are present to ensure there cannot be
        // a deadlock due to all extents held by the redirector and
        // there not be a worker available to release them.
        //

        Objects[0] = &pCommSrvc->IrpPoolHasReleaseEntries;

        Objects[1] = &pCommSrvc->IrpPoolHasEntries;

        //
        // Wait on the 'have items' event until we can retrieve an item
        //

        while( TRUE)
        {

            if( bReleaseRequestThread)
            {

                ntStatus = KeWaitForSingleObject( &pCommSrvc->IrpPoolHasReleaseEntries,
                                                  UserRequest,
                                                  UserMode,
                                                  TRUE,
                                                  NULL);

                if( ntStatus != STATUS_SUCCESS)
                {

                    ntStatus = STATUS_DEVICE_NOT_READY;

                    break;
                }

            }
            else
            {

                ntStatus = KeWaitForMultipleObjects( 2,
                                                     Objects,
                                                     WaitAny,
                                                     UserRequest,
                                                     UserMode,
                                                     TRUE,
                                                     NULL,
                                                     NULL);

                if( ntStatus != STATUS_WAIT_0 &&
                    ntStatus != STATUS_WAIT_1)
                {

                    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);

                //
                // Wake up the next worker since this is a SynchronizationEvent
                //

                KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
                            0,
                            FALSE);

                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( pEntry != NULL)
                {

                    //
                    // There might be another release entry pending
                    //

                    KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
                                0,
                                FALSE);
                }

                //
                // 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
                    {

                        KeSetEvent( &pCommSrvc->IrpPoolHasEntries,
                                    0,
                                    FALSE);
                    }
                }

                //
                // 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;
}
Ejemplo n.º 21
0
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;
}
Ejemplo n.º 22
0
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;
}
Ejemplo n.º 23
0
NTSTATUS
AFSCleanup( IN PDEVICE_OBJECT LibDeviceObject,
            IN PIRP Irp)
{

    NTSTATUS ntStatus = STATUS_SUCCESS;
    AFSDeviceExt *pDeviceExt = NULL;
    IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
    AFSFcb *pFcb = NULL;
    AFSCcb *pCcb = NULL;
    PFILE_OBJECT pFileObject = NULL;
    AFSFcb *pRootFcb = NULL;
    AFSDeviceExt *pControlDeviceExt = NULL;
    IO_STATUS_BLOCK stIoSB;
    AFSObjectInfoCB *pObjectInfo = NULL;
    AFSFileCleanupCB stFileCleanup;
    ULONG   ulNotificationFlags = 0;

    __try
    {

        if( AFSRDRDeviceObject == NULL)
        {

            //
            // Let this through, it's a cleanup on the library control device
            //

            try_return( ntStatus);
        }

        pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
        pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;

        //
        // Set some initial variables to make processing easier
        //

        pFileObject = pIrpSp->FileObject;

        pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;

        pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

        if( pFcb == NULL)
        {
            try_return( ntStatus);
        }

        pObjectInfo = pFcb->ObjectInformation;

        pRootFcb = pObjectInfo->VolumeCB->RootFcb;

        RtlZeroMemory( &stFileCleanup,
                       sizeof( AFSFileCleanupCB));

        stFileCleanup.ProcessId = (ULONGLONG)PsGetCurrentProcessId();

        stFileCleanup.Identifier = (ULONGLONG)pFileObject;

        //
        // Perform the cleanup functionality depending on the type of node it is
        //

        switch( pFcb->Header.NodeTypeCode)
        {

            case AFS_ROOT_ALL:
            {

                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup Acquiring GlobalRoot lock %08lX EXCL %08lX\n",
                              &pFcb->NPFcb->Resource,
                              PsGetCurrentThread());

                AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                  TRUE);

                ASSERT( pFcb->OpenHandleCount != 0);

                InterlockedDecrement( &pFcb->OpenHandleCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup (RootAll) Decrement handle count on Fcb %08lX Cnt %d\n",
                              pFcb,
                              pFcb->OpenHandleCount);

                AFSReleaseResource( &pFcb->NPFcb->Resource);

                FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
                                    &pControlDeviceExt->Specific.Control.DirNotifyList,
                                    pCcb);

                break;
            }

            case AFS_IOCTL_FCB:
            {

                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup Acquiring PIOCtl lock %08lX EXCL %08lX\n",
                              &pFcb->NPFcb->Resource,
                              PsGetCurrentThread());

                AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                  TRUE);

                ASSERT( pFcb->OpenHandleCount != 0);

                InterlockedDecrement( &pFcb->OpenHandleCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup (IOCtl) Decrement handle count on Fcb %08lX Cnt %d\n",
                              pFcb,
                              pFcb->OpenHandleCount);

                //
                // Decrement the open child handle count
                //

                if( pObjectInfo->ParentObjectInformation != NULL &&
                    pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
                {

                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSCleanup (IOCtl) Decrement child open handle count on Parent object %08lX Cnt %d\n",
                                  pObjectInfo->ParentObjectInformation,
                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
                }

                //
                // And finally, release the Fcb if we acquired it.
                //

                AFSReleaseResource( &pFcb->NPFcb->Resource);

                break;
            }

            //
            // This Fcb represents a file
            //

            case AFS_FILE_FCB:
            {

                //
                // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
                //

                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup Acquiring Fcb lock %08lX EXCL %08lX\n",
                              &pFcb->NPFcb->Resource,
                              PsGetCurrentThread());

                AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                TRUE);

                //
                // If the handle has write permission ...
                //

                if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
                    CcIsFileCached( pIrpSp->FileObject))
                {

                    __try
                    {

                        CcFlushCache( &pFcb->NPFcb->SectionObjectPointers,
                                      NULL,
                                      0,
                                      &stIoSB);

                        if( !NT_SUCCESS( stIoSB.Status))
                        {

                            AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
                                          AFS_TRACE_LEVEL_ERROR,
                                          "AFSCleanup CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
                                          &pCcb->FullFileName,
                                          pObjectInfo->FileId.Cell,
                                          pObjectInfo->FileId.Volume,
                                          pObjectInfo->FileId.Vnode,
                                          pObjectInfo->FileId.Unique,
                                          stIoSB.Status,
                                          stIoSB.Information);

                            ntStatus = stIoSB.Status;
                        }
                    }
                    __except( EXCEPTION_EXECUTE_HANDLER)
                    {

                        ntStatus = GetExceptionCode();
                    }
                }

                //
                // Uninitialize the cache map. This call is unconditional.
                //

                AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup Tearing down cache map for Fcb %08lX FileObject %08lX\n",
                              pFcb,
                              pFileObject);

                CcUninitializeCacheMap( pFileObject,
                                        NULL,
                                        NULL);

                //
                // Unlock all outstanding locks on the file, again, unconditionally
                //

                (VOID) FsRtlFastUnlockAll( &pFcb->Specific.File.FileLock,
                                           pFileObject,
                                           IoGetRequestorProcess( Irp),
                                           NULL);

                //
                // Tell the service to unlock all on the file
                //

                ulNotificationFlags |= AFS_REQUEST_FLAG_BYTE_RANGE_UNLOCK_ALL;

                //
                // Perform some final common processing
                //

                ASSERT( pFcb->OpenHandleCount != 0);

                InterlockedDecrement( &pFcb->OpenHandleCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup (File) Decrement handle count on Fcb %08lX Cnt %d\n",
                              pFcb,
                              pFcb->OpenHandleCount);

                if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
                {

                    stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
                }

                stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;

                if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
                {

                    stFileCleanup.AllocationSize = pObjectInfo->EndOfFile;

                    stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
                    {

                        stFileCleanup.CreateTime = pObjectInfo->CreationTime;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
                    }

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
                    {

                        stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
                    }

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
                    {

                        stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
                    }

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME))
                    {

                        stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_LAST_WRITE_TIME | AFS_FCB_FLAG_UPDATE_WRITE_TIME);
                    }
                }

                if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_WRITE_TIME))
                {

                    stFileCleanup.LastWriteTime = pObjectInfo->LastWriteTime;
                }

                //
                // If the count has dropped to zero and there is a pending delete
                // then delete the node
                //

                if( pFcb->OpenHandleCount == 0 &&
                    BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
                {

                    //
                    // Stop anything possibly in process
                    //

                    AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSCleanup Acquiring Fcb extents lock %08lX EXCL %08lX\n",
                                  &pFcb->NPFcb->Specific.File.ExtentsResource,
                                  PsGetCurrentThread());

                    AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
                                    TRUE);

                    pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;

                    KeSetEvent( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
                                0,
                                FALSE);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSCleanup Releasing Fcb extents lock %08lX EXCL %08lX\n",
                                  &pFcb->NPFcb->Specific.File.ExtentsResource,
                                  PsGetCurrentThread());

                    AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);

                    //
                    // Before telling the server about the deleted file, tear down all extents for
                    // the file
                    //

                    AFSTearDownFcbExtents( pFcb,
                                           &pCcb->AuthGroup);

                    ntStatus = STATUS_SUCCESS;

                    ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;

                    //
                    // Indicate the file access mode that is being released
                    //

                    stFileCleanup.FileAccess = pCcb->FileAccess;

                    //
                    // Push the request to the service
                    //

                    ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
                                                  ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
                                                  &pCcb->AuthGroup,
                                                  &pCcb->DirectoryCB->NameInformation.FileName,
                                                  &pObjectInfo->FileId,
                                                  &stFileCleanup,
                                                  sizeof( AFSFileCleanupCB),
                                                  NULL,
                                                  NULL);

                    if( !NT_SUCCESS( ntStatus) &&
                        ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
                    {

                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                      AFS_TRACE_LEVEL_ERROR,
                                      "AFSCleanup Failed to notify service of deleted file %wZ Status %08lX\n",
                                      &pCcb->FullFileName,
                                      ntStatus);

                        ntStatus = STATUS_SUCCESS;

                        ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
                    }
                    else
                    {

                        ntStatus = STATUS_SUCCESS;

                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                      AFS_TRACE_LEVEL_VERBOSE,
                                      "AFSCleanup Setting DELETE flag in file %wZ Dir Entry %p\n",
                                      &pCcb->FullFileName,
                                      pCcb->DirectoryCB);

                        SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);

                        ASSERT( pObjectInfo->ParentObjectInformation != NULL);

                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
                                                        pCcb,
                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
                                                        (ULONG)FILE_ACTION_REMOVED);

                        //
                        // Now that the service has the entry has deleted we need to remove it from the parent
                        // tree so another lookup on the node will fail
                        //

                        if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
                        {

                            AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
                                            TRUE);

                            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                          AFS_TRACE_LEVEL_VERBOSE,
                                          "AFSCleanup DE %p for %wZ removing entry\n",
                                          pCcb->DirectoryCB,
                                          &pCcb->DirectoryCB->NameInformation.FileName);

                            AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
                                                pCcb->DirectoryCB);

                            AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
                        }
                        else
                        {

                            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                          AFS_TRACE_LEVEL_VERBOSE,
                                          "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
                                          pCcb->DirectoryCB,
                                          &pCcb->DirectoryCB->NameInformation.FileName);
                        }
                    }
                }
                else
                {

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
                    {

                        ULONG ulNotifyFilter = 0;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);

                        ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);

                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
                                                        pCcb,
                                                        (ULONG)ulNotifyFilter,
                                                        (ULONG)FILE_ACTION_MODIFIED);
                    }

                    //
                    // Attempt to flush any dirty extents to the server. This may be a little
                    // aggressive, to flush whenever the handle is closed, but it ensures
                    // coherency.
                    //

                    if( (pCcb->GrantedAccess & FILE_WRITE_DATA) &&
                        pFcb->Specific.File.ExtentsDirtyCount != 0)
                    {

                        AFSFlushExtents( pFcb,
                                         &pCcb->AuthGroup);
                    }

                    if( pFcb->OpenHandleCount == 0)
                    {

                        //
                        // Wait for any outstanding queued flushes to complete
                        //

                        AFSWaitOnQueuedFlushes( pFcb);

                        ulNotificationFlags |= AFS_REQUEST_FLAG_FLUSH_FILE;
                    }

                    //
                    // Indicate the file access mode that is being released
                    //

                    stFileCleanup.FileAccess = pCcb->FileAccess;

                    //
                    // Push the request to the service
                    //

                    AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
                                       ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
                                       &pCcb->AuthGroup,
                                       &pCcb->DirectoryCB->NameInformation.FileName,
                                       &pObjectInfo->FileId,
                                       &stFileCleanup,
                                       sizeof( AFSFileCleanupCB),
                                       NULL,
                                       NULL);
                }

                //
                // Remove the share access at this time since we may not get the close for sometime on this FO.
                //

                IoRemoveShareAccess( pFileObject,
                                     &pFcb->ShareAccess);

                //
                // We don't need the name array after the user closes the handle on the file
                //

                if( pCcb->NameArray != NULL)
                {

                    AFSFreeNameArray( pCcb->NameArray);

                    pCcb->NameArray = NULL;
                }

                //
                // Decrement the open child handle count
                //

                if( pObjectInfo->ParentObjectInformation != NULL)
                {

                    ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);

                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSCleanup (File) Decrement child open handle count on Parent object %08lX Cnt %d\n",
                                  pObjectInfo->ParentObjectInformation,
                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
                }

                //
                // And finally, release the Fcb if we acquired it.
                //

                AFSReleaseResource( &pFcb->NPFcb->Resource);

                break;
            }

            //
            // Root or directory node
            //

            case AFS_ROOT_FCB:
            {

                //
                // Set the root Fcb to this node
                //

                pRootFcb = pFcb;

                //
                // Fall through to below
                //
            }

            case AFS_DIRECTORY_FCB:
            {

                //
                // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
                //

                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup Acquiring Dcb lock %08lX EXCL %08lX\n",
                              &pFcb->NPFcb->Resource,
                              PsGetCurrentThread());

                AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                  TRUE);

                //
                // Perform some final common processing
                //

                ASSERT( pFcb->OpenHandleCount != 0);

                InterlockedDecrement( &pFcb->OpenHandleCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup (Dir) Decrement handle count on Fcb %08lX Cnt %d\n",
                              pFcb,
                              pFcb->OpenHandleCount);

                if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
                {

                    stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
                }

                stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;

                if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
                {

                    stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
                    {

                        stFileCleanup.CreateTime = pObjectInfo->CreationTime;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
                    }

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
                    {

                        stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
                    }

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
                    {

                        stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
                    }
                }

                //
                // If the count has dropped to zero and there is a pending delete
                // then delete the node
                //

                if( pFcb->OpenHandleCount == 0 &&
                    BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
                {

                    //
                    // Try to notify the service about the delete
                    //

                    ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;

                    //
                    // Indicate the file access mode that is being released
                    //

                    stFileCleanup.FileAccess = pCcb->FileAccess;

                    //
                    // Push the request to the service
                    //

                    ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
                                                  ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
                                                  &pCcb->AuthGroup,
                                                  &pCcb->DirectoryCB->NameInformation.FileName,
                                                  &pObjectInfo->FileId,
                                                  &stFileCleanup,
                                                  sizeof( AFSFileCleanupCB),
                                                  NULL,
                                                  NULL);

                    if( !NT_SUCCESS( ntStatus) &&
                        ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
                    {

                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                      AFS_TRACE_LEVEL_ERROR,
                                      "AFSCleanup Failed to notify service of deleted directory %wZ Status %08lX\n",
                                      &pCcb->FullFileName,
                                      ntStatus);

                        ntStatus = STATUS_SUCCESS;

                        ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
                    }
                    else
                    {

                        ntStatus = STATUS_SUCCESS;

                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                      AFS_TRACE_LEVEL_VERBOSE,
                                      "AFSCleanup Setting DELETE flag in directory %wZ Dir Entry %p\n",
                                      &pCcb->FullFileName,
                                      pCcb->DirectoryCB);

                        SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);

                        ASSERT( pObjectInfo->ParentObjectInformation != NULL);

                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
                                                        pCcb,
                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
                                                        (ULONG)FILE_ACTION_REMOVED);

                        //
                        // Now that the service has the entry has deleted we need to remove it from the parent
                        // tree so another lookup on the node will fail
                        //

                        if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
                        {

                            AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
                                            TRUE);

                            AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
                                                pCcb->DirectoryCB);

                            AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
                        }
                        else
                        {

                            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                          AFS_TRACE_LEVEL_VERBOSE,
                                          "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
                                          pCcb->DirectoryCB,
                                          &pCcb->DirectoryCB->NameInformation.FileName);
                        }
                    }
                }

                //
                // If there have been any updates to the node then push it to
                // the service
                //

                else
                {

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
                    {

                        ULONG ulNotifyFilter = 0;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);

                        if(  pObjectInfo->ParentObjectInformation != NULL)
                        {

                            ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);

                            AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
                                                            pCcb,
                                                            (ULONG)ulNotifyFilter,
                                                            (ULONG)FILE_ACTION_MODIFIED);
                        }
                    }

                    //
                    // Indicate the file access mode that is being released
                    //

                    stFileCleanup.FileAccess = pCcb->FileAccess;

                    AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
                                       ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
                                       &pCcb->AuthGroup,
                                       &pCcb->DirectoryCB->NameInformation.FileName,
                                       &pObjectInfo->FileId,
                                       &stFileCleanup,
                                       sizeof( AFSFileCleanupCB),
                                       NULL,
                                       NULL);
                }

                //
                // Release the notification for this directory if there is one
                //

                FsRtlNotifyCleanup( pControlDeviceExt->Specific.Control.NotifySync,
                                    &pControlDeviceExt->Specific.Control.DirNotifyList,
                                    pCcb);

                //
                // Remove the share access at this time since we may not get the close for sometime on this FO.
                //

                IoRemoveShareAccess( pFileObject,
                                     &pFcb->ShareAccess);

                //
                // We don't need the name array after the user closes the handle on the file
                //

                if( pCcb->NameArray != NULL)
                {

                    AFSFreeNameArray( pCcb->NameArray);

                    pCcb->NameArray = NULL;
                }

                //
                // Decrement the open child handle count
                //

                if( pObjectInfo->ParentObjectInformation != NULL)
                {

                    ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);

                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSCleanup (Dir) Decrement child open handle count on Parent object %08lX Cnt %d\n",
                                  pObjectInfo->ParentObjectInformation,
                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
                }

                //
                // And finally, release the Fcb if we acquired it.
                //

                AFSReleaseResource( &pFcb->NPFcb->Resource);

                break;
            }

            case AFS_SYMBOLIC_LINK_FCB:
            case AFS_MOUNT_POINT_FCB:
            case AFS_DFS_LINK_FCB:
            case AFS_INVALID_FCB:
            {

                //
                // We may be performing some cleanup on the Fcb so grab it exclusive to ensure no collisions
                //

                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup (MP/SL) Acquiring Dcb lock %08lX EXCL %08lX\n",
                              &pFcb->NPFcb->Resource,
                              PsGetCurrentThread());

                AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                  TRUE);

                //
                // Perform some final common processing
                //

                ASSERT( pFcb->OpenHandleCount != 0);

                InterlockedDecrement( &pFcb->OpenHandleCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup (MP/SL) Decrement handle count on Fcb %08lX Cnt %d\n",
                              pFcb,
                              pFcb->OpenHandleCount);

                if( pFcb->ObjectInformation->ParentObjectInformation != NULL)
                {

                    stFileCleanup.ParentId = pFcb->ObjectInformation->ParentObjectInformation->FileId;
                }

                stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;

                if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
                {

                    stFileCleanup.FileAttributes = pObjectInfo->FileAttributes;

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME))
                    {

                        stFileCleanup.CreateTime = pObjectInfo->CreationTime;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CREATE_TIME);
                    }

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME))
                    {

                        stFileCleanup.ChangeTime = pObjectInfo->ChangeTime;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_CHANGE_TIME);
                    }

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME))
                    {

                        stFileCleanup.LastAccessTime = pObjectInfo->LastAccessTime;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_UPDATE_ACCESS_TIME);
                    }
                }

                //
                // If the count has dropped to zero and there is a pending delete
                // then delete the node
                //

                if( pFcb->OpenHandleCount == 0 &&
                    BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
                {

                    //
                    // Try to notify the service about the delete
                    //

                    ulNotificationFlags |= AFS_REQUEST_FLAG_FILE_DELETED;

                    //
                    // Indicate the file access mode that is being released
                    //

                    stFileCleanup.FileAccess = pCcb->FileAccess;

                    //
                    // Push the request to the service
                    //

                    ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
                                                  ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
                                                  &pCcb->AuthGroup,
                                                  &pCcb->DirectoryCB->NameInformation.FileName,
                                                  &pObjectInfo->FileId,
                                                  &stFileCleanup,
                                                  sizeof( AFSFileCleanupCB),
                                                  NULL,
                                                  NULL);

                    if( !NT_SUCCESS( ntStatus) &&
                        ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
                    {

                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                      AFS_TRACE_LEVEL_ERROR,
                                      "AFSCleanup Failed to notify service of deleted MP/SL %wZ Status %08lX\n",
                                      &pCcb->FullFileName,
                                      ntStatus);

                        ntStatus = STATUS_SUCCESS;

                        ClearFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
                    }
                    else
                    {

                        ntStatus = STATUS_SUCCESS;

                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                      AFS_TRACE_LEVEL_VERBOSE,
                                      "AFSCleanup Setting DELETE flag in MP/SL %wZ Dir Entry %p\n",
                                      &pCcb->FullFileName,
                                      pCcb->DirectoryCB);

                        SetFlag( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_DELETED);

                        ASSERT( pObjectInfo->ParentObjectInformation != NULL);

                        AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
                                                        pCcb,
                                                        (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
                                                        (ULONG)FILE_ACTION_REMOVED);

                        //
                        // Now that the service has the entry has deleted we need to remove it from the parent
                        // tree so another lookup on the node will fail
                        //

                        if( !BooleanFlagOn( pCcb->DirectoryCB->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
                        {

                            AFSAcquireExcl( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
                                            TRUE);

                            AFSRemoveNameEntry( pObjectInfo->ParentObjectInformation,
                                                pCcb->DirectoryCB);

                            AFSReleaseResource( pObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
                        }
                        else
                        {

                            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                          AFS_TRACE_LEVEL_VERBOSE,
                                          "AFSCleanup DE %p for %wZ NOT removing entry due to flag set\n",
                                          pCcb->DirectoryCB,
                                          &pCcb->DirectoryCB->NameInformation.FileName);
                        }
                    }
                }

                //
                // If there have been any updates to the node then push it to
                // the service
                //

                else
                {

                    if( BooleanFlagOn( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED))
                    {

                        ULONG ulNotifyFilter = 0;

                        ClearFlag( pFcb->Flags, AFS_FCB_FLAG_FILE_MODIFIED);

                        if(  pObjectInfo->ParentObjectInformation != NULL)
                        {

                            ulNotifyFilter |= (FILE_NOTIFY_CHANGE_ATTRIBUTES);

                            AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
                                                            pCcb,
                                                            (ULONG)ulNotifyFilter,
                                                            (ULONG)FILE_ACTION_MODIFIED);
                        }
                    }

                    //
                    // Indicate the file access mode that is being released
                    //

                    stFileCleanup.FileAccess = pCcb->FileAccess;

                    AFSProcessRequest( AFS_REQUEST_TYPE_CLEANUP_PROCESSING,
                                       ulNotificationFlags | AFS_REQUEST_FLAG_SYNCHRONOUS,
                                       &pCcb->AuthGroup,
                                       &pCcb->DirectoryCB->NameInformation.FileName,
                                       &pObjectInfo->FileId,
                                       &stFileCleanup,
                                       sizeof( AFSFileCleanupCB),
                                       NULL,
                                       NULL);
                }

                //
                // Remove the share access at this time since we may not get the close for sometime on this FO.
                //

                IoRemoveShareAccess( pFileObject,
                                     &pFcb->ShareAccess);

                //
                // We don't need the name array after the user closes the handle on the file
                //

                if( pCcb->NameArray != NULL)
                {

                    AFSFreeNameArray( pCcb->NameArray);

                    pCcb->NameArray = NULL;
                }

                //
                // Decrement the open child handle count
                //

                if( pObjectInfo->ParentObjectInformation != NULL)
                {

                    ASSERT( pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0);

                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSCleanup (MP/SL) Decrement child open handle count on Parent object %08lX Cnt %d\n",
                                  pObjectInfo->ParentObjectInformation,
                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
                }

                //
                // And finally, release the Fcb if we acquired it.
                //

                AFSReleaseResource( &pFcb->NPFcb->Resource);

                break;
            }

            case AFS_SPECIAL_SHARE_FCB:
            {

                AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup Acquiring SPECIAL SHARE lock %08lX EXCL %08lX\n",
                              &pFcb->NPFcb->Resource,
                              PsGetCurrentThread());

                AFSAcquireExcl( &pFcb->NPFcb->Resource,
                                TRUE);

                ASSERT( pFcb->OpenHandleCount != 0);

                InterlockedDecrement( &pFcb->OpenHandleCount);

                AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                              AFS_TRACE_LEVEL_VERBOSE,
                              "AFSCleanup (Share) Decrement handle count on Fcb %08lX Cnt %d\n",
                              pFcb,
                              pFcb->OpenHandleCount);

                //
                // Decrement the open child handle count
                //

                if( pObjectInfo->ParentObjectInformation != NULL &&
                    pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount > 0)
                {

                    InterlockedDecrement( &pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSCleanup (Share) Decrement child open handle count on Parent object %08lX Cnt %d\n",
                                  pObjectInfo->ParentObjectInformation,
                                  pObjectInfo->ParentObjectInformation->Specific.Directory.ChildOpenHandleCount);
                }

                //
                // And finally, release the Fcb if we acquired it.
                //

                AFSReleaseResource( &pFcb->NPFcb->Resource);

                break;
            }

            default:

                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_WARNING,
                              "AFSCleanup Processing unknown node type %d\n",
                              pFcb->Header.NodeTypeCode);

                break;
        }


try_exit:

        if( pFileObject != NULL)
        {

            //
            // Setup the fileobject flags to indicate cleanup is complete.
            //

            SetFlag( pFileObject->Flags, FO_CLEANUP_COMPLETE);
        }

        //
        // Complete the request
        //

        AFSCompleteRequest( Irp, ntStatus);
    }
Ejemplo n.º 24
0
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( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
    {

        AFSDumpTraceFilesFnc();

        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;
}
Ejemplo n.º 25
0
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;
}
Ejemplo n.º 26
0
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
        // (everyone waits on IrpPoolHasReleaseEntries)
        //

        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;
}
Ejemplo n.º 27
0
NTSTATUS
AFSInitFcb( IN AFSDirectoryCB  *DirEntry,
            IN OUT AFSFcb     **Fcb)
{

    NTSTATUS ntStatus = STATUS_SUCCESS;
    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
    AFSFcb *pFcb = NULL;
    AFSNonPagedFcb *pNPFcb = NULL;
    IO_STATUS_BLOCK stIoSb = {0,0};
    BOOLEAN bUninitFileLock = FALSE;
    USHORT  usFcbLength = 0;
    ULONGLONG   ullIndex = 0;
    AFSDirEnumEntry *pDirEnumCB = NULL;
    AFSObjectInfoCB *pObjectInfo = NULL, *pParentObjectInfo = NULL;
    AFSVolumeCB *pVolumeCB = NULL;

    __Enter
    {

        pObjectInfo = DirEntry->ObjectInformation;

        pParentObjectInfo = pObjectInfo->ParentObjectInformation;

        pVolumeCB = pObjectInfo->VolumeCB;

        //
        // Allocate the Fcb and the nonpaged portion of the Fcb.
        //

        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE_2,
                      "AFSInitFcb Initializing fcb for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
                      &DirEntry->NameInformation.FileName,
                      pObjectInfo->FileId.Cell,
                      pObjectInfo->FileId.Volume,
                      pObjectInfo->FileId.Vnode,
                      pObjectInfo->FileId.Unique);

        usFcbLength = sizeof( AFSFcb);

        pFcb = (AFSFcb *)AFSExAllocatePoolWithTag( PagedPool,
                                                   usFcbLength,
                                                   AFS_FCB_ALLOCATION_TAG);

        if( pFcb == NULL)
        {

            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSInitFcb Failed to allocate fcb\n");

            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
        }

        RtlZeroMemory( pFcb,
                       usFcbLength);

        pFcb->Header.NodeByteSize = usFcbLength;

        pNPFcb = (AFSNonPagedFcb *)AFSExAllocatePoolWithTag( NonPagedPool,
                                                             sizeof( AFSNonPagedFcb),
                                                             AFS_FCB_NP_ALLOCATION_TAG);

        if( pNPFcb == NULL)
        {

            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSInitFcb Failed to allocate non-paged fcb\n");

            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
        }

        RtlZeroMemory( pNPFcb,
                       sizeof( AFSNonPagedFcb));

        pNPFcb->Size = sizeof( AFSNonPagedFcb);
        pNPFcb->Type = AFS_NON_PAGED_FCB;

        //
        // Initialize the advanced header
        //

        ExInitializeFastMutex( &pNPFcb->AdvancedHdrMutex);

        FsRtlSetupAdvancedHeader( &pFcb->Header, &pNPFcb->AdvancedHdrMutex);

        //
        // OK, initialize the entry
        //

        ExInitializeResourceLite( &pNPFcb->Resource);

        ExInitializeResourceLite( &pNPFcb->PagingResource);

        ExInitializeResourceLite( &pNPFcb->CcbListLock);

        pFcb->Header.Resource = &pNPFcb->Resource;

        pFcb->Header.PagingIoResource = &pNPFcb->PagingResource;

        //
        // Grab the Fcb for processing
        //

        AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSInitFcb Acquiring Fcb lock %08lX EXCL %08lX\n",
                      &pNPFcb->Resource,
                      PsGetCurrentThread());

        AFSAcquireExcl( &pNPFcb->Resource,
                        TRUE);

        pFcb->NPFcb = pNPFcb;

        //
        // Initialize some fields in the Fcb
        //

        pFcb->ObjectInformation = pObjectInfo;

        pObjectInfo->Fcb = pFcb;

        //
        // Set type specific information
        //

        if( pObjectInfo->FileType == AFS_FILE_TYPE_DIRECTORY)
        {

            //
            // Reset the type to a directory type
            //

            pFcb->Header.NodeTypeCode = AFS_DIRECTORY_FCB;

            //
            // Initialize enumeration information
            //

            KeInitializeEvent( &pFcb->NPFcb->Specific.Directory.DirectoryEnumEvent,
                               NotificationEvent,
                               FALSE);
        }
        else if( pObjectInfo->FileType == AFS_FILE_TYPE_FILE)
        {

            pFcb->Header.NodeTypeCode = AFS_FILE_FCB;

            //
            // Initialize the file specific information
            //

            FsRtlInitializeFileLock( &pFcb->Specific.File.FileLock,
                                     NULL,
                                     NULL);

            bUninitFileLock = TRUE;

            //
            // Initialize the header file sizes to our dir entry information
            //

            pFcb->Header.AllocationSize.QuadPart = pObjectInfo->AllocationSize.QuadPart;
            pFcb->Header.FileSize.QuadPart = pObjectInfo->EndOfFile.QuadPart;
            pFcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;

            //
            // Initialize the Extents resources and so forth.  The
            // quiescent state is that no one has the extents for
            // IO (do the extents are not busy) and there is no
            // extents request outstanding (and hence the "last
            // one" is complete).
            //
            ExInitializeResourceLite( &pNPFcb->Specific.File.ExtentsResource );

            KeInitializeEvent( &pNPFcb->Specific.File.ExtentsRequestComplete,
                               NotificationEvent,
                               TRUE );

            for (ULONG i = 0; i < AFS_NUM_EXTENT_LISTS; i++)
            {
                InitializeListHead(&pFcb->Specific.File.ExtentsLists[i]);
            }

            pNPFcb->Specific.File.DirtyListHead = NULL;
            pNPFcb->Specific.File.DirtyListTail = NULL;

            ExInitializeResourceLite( &pNPFcb->Specific.File.DirtyExtentsListLock);

            KeInitializeEvent( &pNPFcb->Specific.File.FlushEvent,
                               SynchronizationEvent,
                               TRUE);

            KeInitializeEvent( &pNPFcb->Specific.File.QueuedFlushEvent,
                               NotificationEvent,
                               TRUE);
        }
        else if( pObjectInfo->FileType == AFS_FILE_TYPE_SPECIAL_SHARE_NAME)
        {

            pFcb->Header.NodeTypeCode = AFS_SPECIAL_SHARE_FCB;
        }
        else if( pObjectInfo->FileType == AFS_FILE_TYPE_PIOCTL)
        {

            pFcb->Header.NodeTypeCode = AFS_IOCTL_FCB;
        }
        else if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK)
        {

            pFcb->Header.NodeTypeCode = AFS_SYMBOLIC_LINK_FCB;
        }
        else if( pObjectInfo->FileType == AFS_FILE_TYPE_MOUNTPOINT)
        {

            pFcb->Header.NodeTypeCode = AFS_MOUNT_POINT_FCB;
        }
        else if( pObjectInfo->FileType == AFS_FILE_TYPE_DFSLINK)
        {
            pFcb->Header.NodeTypeCode = AFS_DFS_LINK_FCB;
        }
        else
        {
            pFcb->Header.NodeTypeCode = AFS_INVALID_FCB;
        }

        //
        // And return the Fcb
        //

        *Fcb = pFcb;

        AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "AFSInitFcb Initialized Fcb %08lX Name %wZ\n",
                      pFcb,
                      &DirEntry->NameInformation.FileName);

try_exit:

        if( !NT_SUCCESS( ntStatus))
        {

            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSInitFcb Failed to initialize fcb Status %08lX\n",
                          ntStatus);

            if( pFcb != NULL)
            {

                if( bUninitFileLock)
                {

                    FsRtlUninitializeFileLock( &pFcb->Specific.File.FileLock);
                }

                if( pNPFcb != NULL)
                {

                    AFSReleaseResource( &pNPFcb->Resource);

                    ExDeleteResourceLite( &pNPFcb->PagingResource);

                    ExDeleteResourceLite( &pNPFcb->CcbListLock);

                    ExDeleteResourceLite( &pNPFcb->Resource);
                }

                AFSExFreePool( pFcb);
            }

            if( pNPFcb != NULL)
            {

                AFSExFreePool( pNPFcb);
            }

            if( Fcb != NULL)
            {

                *Fcb = NULL;
            }
        }
    }

    return ntStatus;
}
Ejemplo n.º 28
0
NTSTATUS
AFSProcessUserFsRequest( IN PIRP Irp)
{

    NTSTATUS ntStatus = STATUS_SUCCESS;
    ULONG ulFsControlCode;
    AFSFcb *pFcb = NULL;
    PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp );
    AFSCcb *pCcb = NULL;
    ULONG ulOutputBufferLen, ulInputBufferLen;

    __Enter
    {

        ulFsControlCode = pIrpSp->Parameters.FileSystemControl.FsControlCode;

        pFcb = (AFSFcb *)pIrpSp->FileObject->FsContext;

        pCcb = (AFSCcb *)pIrpSp->FileObject->FsContext2;

        if( pFcb == NULL ||
            pCcb->DirectoryCB == NULL)
        {

            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_VERBOSE_2,
                          "AFSProcessUserFsRequest Invalid Fcb\n");

            try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
        }

        if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
        {

            ntStatus = AFSProcessShareFsCtrl( Irp,
                                              pFcb,
                                              pCcb);

            try_return( ntStatus);
        }

        ulOutputBufferLen = pIrpSp->Parameters.FileSystemControl.OutputBufferLength;
        ulInputBufferLen = pIrpSp->Parameters.FileSystemControl.InputBufferLength;

        //
        // Process the request
        //

        switch( ulFsControlCode )
        {

            case FSCTL_REQUEST_OPLOCK_LEVEL_1:
            case FSCTL_REQUEST_OPLOCK_LEVEL_2:
            case FSCTL_REQUEST_BATCH_OPLOCK:
            case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE:
            case FSCTL_OPBATCH_ACK_CLOSE_PENDING:
            case FSCTL_OPLOCK_BREAK_NOTIFY:
            case FSCTL_OPLOCK_BREAK_ACK_NO_2:
            case FSCTL_REQUEST_FILTER_OPLOCK :
            {
                //
                // Note that implementing this call will probably need us
                // to call the server as well as adding code in read and
                // write and caching.  Also that it is unlikely that
                // anyone will ever call us at this point - RDR doesn't
                // allow it
                //

                ntStatus = STATUS_NOT_IMPLEMENTED;

                break;
            }

            case FSCTL_LOCK_VOLUME:
            {
                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing FSCTL_LOCK_VOLUME request\n");

                ntStatus = STATUS_NOT_IMPLEMENTED;

                break;
            }

            case FSCTL_UNLOCK_VOLUME:
            {
                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing FSCTL_UNLOCK_VOLUME request\n");

                ntStatus = STATUS_NOT_IMPLEMENTED;

                break;
            }

            case FSCTL_DISMOUNT_VOLUME:
            {
                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing FSCTL_DISMOUNT_VOLUME request\n");

                ntStatus = STATUS_NOT_IMPLEMENTED;

                break;
            }

            case FSCTL_MARK_VOLUME_DIRTY:
            {
                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing FSCTL_MARK_VOLUME_DIRTY request\n");

                ntStatus = STATUS_NOT_IMPLEMENTED;

                break;
            }

            case FSCTL_IS_VOLUME_DIRTY:
            {
                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing FSCTL_IS_VOLUME_DIRTY request\n");

                ntStatus = STATUS_NOT_IMPLEMENTED;

                break;
            }

            case FSCTL_IS_VOLUME_MOUNTED:
            {
                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing FSCTL_IS_VOLUME_MOUNTED request\n");

                ntStatus = STATUS_NOT_IMPLEMENTED;

                break;
            }

            case FSCTL_IS_PATHNAME_VALID:
            {
                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing FSCTL_IS_PATHNAME_VALID request\n");

                ntStatus = STATUS_SUCCESS;

                break;
            }

#ifndef FSCTL_CSC_INTERNAL
#define FSCTL_CSC_INTERNAL                  CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 107, METHOD_NEITHER, FILE_ANY_ACCESS)
#endif
            case FSCTL_CSC_INTERNAL:
            {
                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing FSCTL_CSC_INTERNAL request\n");

                ntStatus = STATUS_INVALID_DEVICE_REQUEST;

                break;
            }

            case FSCTL_GET_REPARSE_POINT:
            {

                REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;
                ULONG ulRemainingLen = ulOutputBufferLen;
                AFSReparseTagInfo *pReparseInfo = NULL;

                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing FSCTL_GET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n",
                              &pCcb->DirectoryCB->NameInformation.FileName,
                              pCcb->DirectoryCB->ObjectInformation->FileType,
                              pCcb->DirectoryCB->ObjectInformation->FileAttributes);

                //
                // Check if we have the reparse entry set on the entry
                //

                if( !BooleanFlagOn( pCcb->DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
                {

                    ntStatus = STATUS_NOT_A_REPARSE_POINT;

                    break;
                }

                if( ulOutputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
                {

                    ntStatus = STATUS_BUFFER_TOO_SMALL;

                    Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer);

                    break;
                }

                ulRemainingLen -= FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer);

                //
                // Populate the data in the reparse buffer
                //

                pReparseBuffer->ReparseDataLength  = 0;

                AFSAcquireExcl( &pCcb->DirectoryCB->NonPaged->Lock,
                                TRUE);

                if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
                {

                    //
                    // We'll reset the DV to ensure we validate the metadata content
                    //

                    pCcb->DirectoryCB->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;

                    SetFlag( pCcb->DirectoryCB->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);

                    AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                  AFS_TRACE_LEVEL_VERBOSE,
                                  "AFSProcessUserFsRequest Verifying symlink %wZ FID %08lX-%08lX-%08lX-%08lX\n",
                                  &pCcb->DirectoryCB->NameInformation.FileName,
                                  pCcb->DirectoryCB->ObjectInformation->FileId.Cell,
                                  pCcb->DirectoryCB->ObjectInformation->FileId.Volume,
                                  pCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
                                  pCcb->DirectoryCB->ObjectInformation->FileId.Unique);

                    ntStatus = AFSVerifyEntry( &pCcb->AuthGroup,
                                               pCcb->DirectoryCB);

                    if( !NT_SUCCESS( ntStatus))
                    {

                        AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                                      AFS_TRACE_LEVEL_ERROR,
                                      "AFSProcessUserFsRequest Failed to verify symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
                                      &pCcb->DirectoryCB->NameInformation.FileName,
                                      pCcb->DirectoryCB->ObjectInformation->FileId.Cell,
                                      pCcb->DirectoryCB->ObjectInformation->FileId.Volume,
                                      pCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
                                      pCcb->DirectoryCB->ObjectInformation->FileId.Unique,
                                      ntStatus);

                        AFSReleaseResource( &pCcb->DirectoryCB->NonPaged->Lock);

                        break;
                    }
                }

                pReparseInfo = (AFSReparseTagInfo *)&pReparseBuffer->GenericReparseBuffer.DataBuffer[ 0];

                switch( pCcb->DirectoryCB->ObjectInformation->FileType)
                {

                    case AFS_FILE_TYPE_SYMLINK:
                    {

                        if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
                        {

                            ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;

                            break;
                        }

                        if( ulRemainingLen < (ULONG) FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length)
                        {

                            ntStatus = STATUS_BUFFER_TOO_SMALL;

                            Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
                                                        FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) +
                                                        pCcb->DirectoryCB->NameInformation.TargetName.Length;

                            break;
                        }

                        pReparseInfo->SubTag = OPENAFS_SUBTAG_SYMLINK;

                        pReparseInfo->AFSSymLink.RelativeLink = AFSIsRelativeName( &pCcb->DirectoryCB->NameInformation.TargetName);

                        pReparseInfo->AFSSymLink.SymLinkTargetLength = pCcb->DirectoryCB->NameInformation.TargetName.Length;

                        RtlCopyMemory( pReparseInfo->AFSSymLink.Buffer,
                                       pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
                                       pCcb->DirectoryCB->NameInformation.TargetName.Length);

                        pReparseBuffer->ReparseDataLength = (FIELD_OFFSET( AFSReparseTagInfo, AFSSymLink.Buffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length);

                        break;
                    }

                    case AFS_FILE_TYPE_MOUNTPOINT:
                    {
                        UNICODE_STRING Cell, Volume;
                        USHORT Type;

                        if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
                        {
                            ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;

                            break;
                        }

                        if ( !AFSParseMountPointTarget( &pCcb->DirectoryCB->NameInformation.TargetName,
                                                        &Type,
                                                        &Volume,
                                                        &Cell))
                        {
                            ntStatus = STATUS_INVALID_PARAMETER;

                            break;
                        }

                        if( ulRemainingLen < (ULONG) FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) + Volume.Length + Cell.Length)
                        {

                            ntStatus = STATUS_BUFFER_TOO_SMALL;

                            Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
                                                        FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) +
                                                        Volume.Length + Cell.Length;

                            break;
                        }

                        pReparseInfo->SubTag = OPENAFS_SUBTAG_MOUNTPOINT;

                        pReparseInfo->AFSMountPoint.Type = Type;

                        pReparseInfo->AFSMountPoint.MountPointCellLength = Cell.Length;

                        pReparseInfo->AFSMountPoint.MountPointVolumeLength = Volume.Length;

                        RtlCopyMemory( pReparseInfo->AFSMountPoint.Buffer,
                                       Cell.Buffer,
                                       Cell.Length);

                        RtlCopyMemory( &pReparseInfo->AFSMountPoint.Buffer[ Cell.Length / sizeof( WCHAR)],
                                       Volume.Buffer,
                                       Volume.Length);

                        pReparseBuffer->ReparseDataLength = (FIELD_OFFSET( AFSReparseTagInfo, AFSMountPoint.Buffer) + Volume.Length + Cell.Length);

                        break;
                    }

                    case AFS_FILE_TYPE_DFSLINK:
                    {

                        if( pCcb->DirectoryCB->NameInformation.TargetName.Length == 0)
                        {

                            ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;

                            break;
                        }

                        if( ulRemainingLen < (ULONG) FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length)
                        {

                            ntStatus = STATUS_BUFFER_TOO_SMALL;

                            Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
                                                        FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) +
                                                        pCcb->DirectoryCB->NameInformation.TargetName.Length;

                            break;
                        }

                        pReparseInfo->SubTag = OPENAFS_SUBTAG_UNC;

                        pReparseInfo->UNCReferral.UNCTargetLength = pCcb->DirectoryCB->NameInformation.TargetName.Length;

                        RtlCopyMemory( pReparseInfo->UNCReferral.Buffer,
                                       pCcb->DirectoryCB->NameInformation.TargetName.Buffer,
                                       pCcb->DirectoryCB->NameInformation.TargetName.Length);

                        pReparseBuffer->ReparseDataLength = (FIELD_OFFSET( AFSReparseTagInfo, UNCReferral.Buffer) + pCcb->DirectoryCB->NameInformation.TargetName.Length);

                        break;
                    }

                    default:

                        ntStatus = STATUS_NOT_A_REPARSE_POINT;

                        break;
                }

                if ( ntStatus == STATUS_SUCCESS)
                {

                    ulRemainingLen -= pReparseBuffer->ReparseDataLength;

                    pReparseBuffer->ReparseTag = IO_REPARSE_TAG_SURROGATE|IO_REPARSE_TAG_OPENAFS_DFS;

                    RtlCopyMemory( &pReparseBuffer->ReparseGuid,
                                   &GUID_AFS_REPARSE_GUID,
                                   sizeof( GUID));

                    Irp->IoStatus.Information = FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer) +
                                                              pReparseBuffer->ReparseDataLength;
                }

                AFSReleaseResource( &pCcb->DirectoryCB->NonPaged->Lock);

                break;
            }

            case FSCTL_SET_REPARSE_POINT:
            {

                REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;

                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing FSCTL_SET_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n",
                              &pCcb->DirectoryCB->NameInformation.FileName,
                              pCcb->DirectoryCB->ObjectInformation->FileType,
                              pCcb->DirectoryCB->ObjectInformation->FileAttributes);

                //
                // Check if we have the reparse entry set on the entry
                //

                if( !BooleanFlagOn( pCcb->DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
                {

                    ntStatus = STATUS_NOT_A_REPARSE_POINT;

                    break;
                }

                if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
                {

                    ntStatus = STATUS_IO_REPARSE_DATA_INVALID;

                    break;
                }

                if( (pReparseBuffer->ReparseTag & 0x0000FFFF) != IO_REPARSE_TAG_OPENAFS_DFS)
                {

                    ntStatus = STATUS_IO_REPARSE_TAG_MISMATCH;

                    break;
                }

                if( RtlCompareMemory( &pReparseBuffer->ReparseGuid,
                                      &GUID_AFS_REPARSE_GUID,
                                      sizeof( GUID)) != sizeof( GUID))
                {

                    ntStatus = STATUS_REPARSE_ATTRIBUTE_CONFLICT;

                    break;
                }

                //
                // For now deny access on this call
                //

                ntStatus = STATUS_INVALID_PARAMETER;

                break;
            }

            case FSCTL_DELETE_REPARSE_POINT:
            {

                REPARSE_GUID_DATA_BUFFER *pReparseBuffer = (REPARSE_GUID_DATA_BUFFER *)Irp->AssociatedIrp.SystemBuffer;

                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing FSCTL_DELETE_REPARSE_POINT request %wZ Type 0x%x Attrib 0x%x\n",
                              &pCcb->DirectoryCB->NameInformation.FileName,
                              pCcb->DirectoryCB->ObjectInformation->FileType,
                              pCcb->DirectoryCB->ObjectInformation->FileAttributes);

                //
                // Check if we have the reparse entry set on the entry
                //

                if( !BooleanFlagOn( pCcb->DirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
                {

                    ntStatus = STATUS_NOT_A_REPARSE_POINT;

                    break;
                }

                if( ulInputBufferLen < FIELD_OFFSET( REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer.DataBuffer))
                {

                    ntStatus = STATUS_INVALID_PARAMETER;

                    break;
                }

                if( (pReparseBuffer->ReparseTag & 0x0000FFFF) != IO_REPARSE_TAG_OPENAFS_DFS)
                {

                    ntStatus = STATUS_IO_REPARSE_TAG_MISMATCH;

                    break;
                }

                if( RtlCompareMemory( &pReparseBuffer->ReparseGuid,
                                      &GUID_AFS_REPARSE_GUID,
                                      sizeof( GUID)) != sizeof( GUID))
                {

                    ntStatus = STATUS_REPARSE_ATTRIBUTE_CONFLICT;

                    break;
                }

                //
                // For now deny access on this call
                //

                ntStatus = STATUS_ACCESS_DENIED;

                break;
            }

            default :

                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_VERBOSE_2,
                              "AFSProcessUserFsRequest Processing default (%08lX) request\n", ulFsControlCode);

                ntStatus = STATUS_INVALID_DEVICE_REQUEST;

                break;
        }

try_exit:

        NOTHING;
    }

    return ntStatus;
}
Ejemplo n.º 29
0
NTSTATUS
AFSQueryVolumeInfo( IN PDEVICE_OBJECT LibDeviceObject,
                    IN PIRP Irp)
{

    NTSTATUS ntStatus = STATUS_SUCCESS;
    AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
    IO_STACK_LOCATION *pIrpSp;
    FS_INFORMATION_CLASS FsInformationClass;
    void *pBuffer = NULL;
    ULONG ulLength = 0;
    BOOLEAN bReleaseResource = FALSE;
    PFILE_OBJECT pFileObject = NULL;
    AFSFcb *pFcb = NULL;
    AFSObjectInfoCB *pObjectInfo = NULL;
    AFSVolumeCB *pVolumeCB = NULL;

    pIrpSp = IoGetCurrentIrpStackLocation( Irp);

    __try
    {

        pFileObject = pIrpSp->FileObject;

        if( pFileObject == NULL)
        {

            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSQueryVolumeInfo Failing request with NULL FileObject\n");

            try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
        }

        pFcb = (AFSFcb *)pFileObject->FsContext;

        if( pFcb == NULL)
        {

            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSQueryVolumeInfo Failing request with NULL Fcb\n");

            try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
        }

        pObjectInfo = pFcb->ObjectInformation;

        if( pObjectInfo == NULL)
        {

            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSQueryVolumeInfo Failing request with NULL ObjectInformation\n");

            try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
        }

        pVolumeCB = pObjectInfo->VolumeCB;

        ulLength = pIrpSp->Parameters.QueryVolume.Length;
        FsInformationClass = pIrpSp->Parameters.QueryVolume.FsInformationClass;
        pBuffer = Irp->AssociatedIrp.SystemBuffer;

        AFSAcquireShared( pVolumeCB->VolumeLock,
                          TRUE);

        bReleaseResource = TRUE;

        //
        // Don't allow requests against IOCtl nodes
        //

        if( pFcb->Header.NodeTypeCode == AFS_IOCTL_FCB)
        {

            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSQueryVolumeInfo Failing request against PIOCtl Fcb\n");

            try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
        }
        else if( pFcb->Header.NodeTypeCode == AFS_SPECIAL_SHARE_FCB)
        {

            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSQueryVolumeInfo Failing request against SpecialShare Fcb\n");

            try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
        }
        else if( pFcb->Header.NodeTypeCode == AFS_INVALID_FCB)
        {

            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSQueryVolumeInfo Failing request against SpecialShare Fcb\n");

            try_return( ntStatus = STATUS_INVALID_DEVICE_REQUEST);
        }

        //
        // Process the request
        //

        switch( FsInformationClass)
        {

            case FileFsVolumeInformation:
            {

                ntStatus = AFSQueryFsVolumeInfo( &pVolumeCB->VolumeInformation,
                                                 (PFILE_FS_VOLUME_INFORMATION)pBuffer,
                                                 &ulLength);

                break;
            }

            case FileFsSizeInformation:
            {

                ntStatus = AFSQueryFsSizeInfo( &pVolumeCB->VolumeInformation,
                                               (PFILE_FS_SIZE_INFORMATION)pBuffer,
                                               &ulLength);

                break;
            }

            case FileFsDeviceInformation:
            {

                ntStatus = AFSQueryFsDeviceInfo( &pVolumeCB->VolumeInformation,
                                                 (PFILE_FS_DEVICE_INFORMATION)pBuffer,
                                                 &ulLength);

                break;
            }

            case FileFsAttributeInformation:
            {

                ntStatus = AFSQueryFsAttributeInfo( &pVolumeCB->VolumeInformation,
                                                    (PFILE_FS_ATTRIBUTE_INFORMATION)pBuffer,
                                                    &ulLength);

                break;
            }

            case FileFsFullSizeInformation:
            {

                ntStatus = AFSQueryFsFullSizeInfo( &pVolumeCB->VolumeInformation,
                                                   (PFILE_FS_FULL_SIZE_INFORMATION)pBuffer,
                                                   &ulLength);

                break;
            }

            default:

                AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
                              AFS_TRACE_LEVEL_WARNING,
                              "AFSQueryVolumeInfo Invalid class %d\n",
                              FsInformationClass);

                ntStatus = STATUS_INVALID_PARAMETER;

                break;
        }

try_exit:

        //
        // Setup the Irp's information field to what we actually copied in.
        //

        Irp->IoStatus.Information = pIrpSp->Parameters.QueryVolume.Length - ulLength;

        if( bReleaseResource)
        {

            AFSReleaseResource( pVolumeCB->VolumeLock);
        }

        AFSCompleteRequest( Irp,
                            ntStatus);

    }
    __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
    {

        AFSDbgLogMsg( 0,
                      0,
                      "EXCEPTION - AFSQueryVolumeInfo FO %08lX InfoClass %d FCB %08lX ObjectInfo %08lX VolCB %08lX\n",
                      pFileObject,
                      FsInformationClass,
                      pFcb,
                      pObjectInfo,
                      pVolumeCB);

        AFSDumpTraceFilesFnc();
    }

    return ntStatus;
}
Ejemplo n.º 30
0
NTSTATUS
AFSLoadLibrary( IN ULONG Flags,
                IN UNICODE_STRING *ServicePath)
{
    UNREFERENCED_PARAMETER(Flags);

    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
        //

        AFSDbgTrace(( 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))
        {

            AFSDbgTrace(( 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))
        {

            AFSDbgTrace(( 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)
        {

            AFSDbgTrace(( 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))
        {

            AFSDbgTrace(( 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))
        {
            AFSDbgTrace(( 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);

        AFSDbgTrace(( 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:

        AFSDbgTrace(( 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;
}