⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rw.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * COPYRIGHT:  See COPYING in the top level directory
 * PROJECT:    ReactOS kernel
 * FILE:       drivers/fs/np/rw.c
 * PURPOSE:    Named pipe filesystem
 * PROGRAMMER: David Welch <welch@cwcom.net>
 */

/* INCLUDES ******************************************************************/

#define NDEBUG
#include <debug.h>

#include "npfs.h"

/* FUNCTIONS *****************************************************************/

#ifndef NDEBUG
VOID HexDump(PUCHAR Buffer, ULONG Length)
{
  CHAR Line[65];
  UCHAR ch;
  const char Hex[] = "0123456789ABCDEF";
  int i, j;

  DbgPrint("---------------\n");

  for (i = 0; i < Length; i+= 16)
    {
      memset(Line, ' ', 64);
      Line[64] = 0;

      for (j = 0; j < 16 && j + i < Length; j++)
        {
          ch = Buffer[i + j];
          Line[3*j + 0] = Hex[ch >> 4];
	  Line[3*j + 1] = Hex[ch & 0x0f];
	  Line[48 + j] = isprint(ch) ? ch : '.';
        }
      DbgPrint("%s\n", Line);
    }
  DbgPrint("---------------\n");
}
#endif

static VOID STDCALL
NpfsReadWriteCancelRoutine(IN PDEVICE_OBJECT DeviceObject,
                           IN PIRP Irp)
{
   PNPFS_CONTEXT Context;
   PNPFS_DEVICE_EXTENSION DeviceExt;
   PIO_STACK_LOCATION IoStack;
   PNPFS_CCB Ccb;
   BOOLEAN Complete = FALSE;

   DPRINT("NpfsReadWriteCancelRoutine(DeviceObject %x, Irp %x)\n", DeviceObject, Irp);

   IoReleaseCancelSpinLock(Irp->CancelIrql);

   Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext;
   DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
   IoStack = IoGetCurrentIrpStackLocation(Irp);
   Ccb = IoStack->FileObject->FsContext2;

   KeLockMutex(&DeviceExt->PipeListLock);
   ExAcquireFastMutex(&Ccb->DataListLock);
   switch(IoStack->MajorFunction)
   {
      case IRP_MJ_READ:
         if (Ccb->ReadRequestListHead.Flink != &Context->ListEntry)
	 {
	    /* we are not the first in the list, remove an complete us */
	    RemoveEntryList(&Context->ListEntry);
	    Complete = TRUE;
	 }
	 else
	 {
	    KeSetEvent(&Ccb->ReadEvent, IO_NO_INCREMENT, FALSE);
	 }
	 break;
      default:
         KEBUGCHECK(0);
   }
   ExReleaseFastMutex(&Ccb->DataListLock);
   KeUnlockMutex(&DeviceExt->PipeListLock);
   if (Complete)
   {
      Irp->IoStatus.Status = STATUS_CANCELLED;
      Irp->IoStatus.Information = 0;
      IoCompleteRequest(Irp, IO_NO_INCREMENT);
   }
}

static VOID STDCALL
NpfsWaiterThread(PVOID InitContext)
{
   PNPFS_THREAD_CONTEXT ThreadContext = (PNPFS_THREAD_CONTEXT) InitContext;
   ULONG CurrentCount;
   ULONG Count = 0;
   PIRP Irp = NULL;
   PIRP NextIrp;
   NTSTATUS Status;
   BOOLEAN Terminate = FALSE;
   BOOLEAN Cancel = FALSE;
   PIO_STACK_LOCATION IoStack = NULL;
   PNPFS_CONTEXT Context;
   PNPFS_CONTEXT NextContext;
   PNPFS_CCB Ccb;

   KeLockMutex(&ThreadContext->DeviceExt->PipeListLock);

   while (1)
     {
       CurrentCount = ThreadContext->Count;
       KeUnlockMutex(&ThreadContext->DeviceExt->PipeListLock);
       if (Irp)
         {
           if (Cancel)
             {
	       Irp->IoStatus.Status = STATUS_CANCELLED;
               Irp->IoStatus.Information = 0;
               IoCompleteRequest(Irp, IO_NO_INCREMENT);
	     }
	   else
	     {
               switch (IoStack->MajorFunction)
	         {
	           case IRP_MJ_READ:
                     NpfsRead(IoStack->DeviceObject, Irp);
		     break;
		   default:
		     KEBUGCHECK(0);
		 }
	     }
         }
       if (Terminate)
         {
	   break;
	 }
       Status = KeWaitForMultipleObjects(CurrentCount,
	                                 ThreadContext->WaitObjectArray,
					 WaitAny,
					 Executive,
					 KernelMode,
					 FALSE,
					 NULL,
					 ThreadContext->WaitBlockArray);
       if (!NT_SUCCESS(Status))
         {
           KEBUGCHECK(0);
         }
       KeLockMutex(&ThreadContext->DeviceExt->PipeListLock);
       Count = Status - STATUS_SUCCESS;
       ASSERT (Count < CurrentCount);
       if (Count > 0)
       {
	  Irp = ThreadContext->WaitIrpArray[Count];
	  ThreadContext->Count--;
	  ThreadContext->DeviceExt->EmptyWaiterCount++;
	  ThreadContext->WaitObjectArray[Count] = ThreadContext->WaitObjectArray[ThreadContext->Count];
	  ThreadContext->WaitIrpArray[Count] = ThreadContext->WaitIrpArray[ThreadContext->Count];

          Cancel = (NULL == IoSetCancelRoutine(Irp, NULL));
	  Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext;
	  IoStack = IoGetCurrentIrpStackLocation(Irp);

	  if (Cancel)
	  {
	     Ccb = IoStack->FileObject->FsContext2;
 	     ExAcquireFastMutex(&Ccb->DataListLock);
	     RemoveEntryList(&Context->ListEntry);
	     switch (IoStack->MajorFunction)
	     {
	        case IRP_MJ_READ:
                   if (!IsListEmpty(&Ccb->ReadRequestListHead))
		   {
		      /* put the next request on the wait list */
                      NextContext = CONTAINING_RECORD(Ccb->ReadRequestListHead.Flink, NPFS_CONTEXT, ListEntry);
		      ThreadContext->WaitObjectArray[ThreadContext->Count] = NextContext->WaitEvent;
		      NextIrp = CONTAINING_RECORD(NextContext, IRP, Tail.Overlay.DriverContext);
		      ThreadContext->WaitIrpArray[ThreadContext->Count] = NextIrp;
		      ThreadContext->Count++;
                      ThreadContext->DeviceExt->EmptyWaiterCount--;
		   }
		   break;
		default:
		   KEBUGCHECK(0);
	     }
	     ExReleaseFastMutex(&Ccb->DataListLock);
	  }
       }
       else
       {
	  /* someone has add a new wait request */
          Irp = NULL;
       }
       if (ThreadContext->Count == 1 && ThreadContext->DeviceExt->EmptyWaiterCount >= MAXIMUM_WAIT_OBJECTS)
        {
          /* it exist an other thread with empty wait slots, we can remove our thread from the list */
          RemoveEntryList(&ThreadContext->ListEntry);
          ThreadContext->DeviceExt->EmptyWaiterCount -= MAXIMUM_WAIT_OBJECTS - 1;
	  Terminate = TRUE;
        }
     }
   ExFreePool(ThreadContext);
}

static NTSTATUS
NpfsAddWaitingReadWriteRequest(IN PDEVICE_OBJECT DeviceObject,
			       IN PIRP Irp)
{
   PLIST_ENTRY ListEntry;
   PNPFS_THREAD_CONTEXT ThreadContext = NULL;
   NTSTATUS Status;
   HANDLE hThread;
   KIRQL oldIrql;

   PNPFS_CONTEXT Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext;
   PNPFS_DEVICE_EXTENSION DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

   DPRINT("NpfsAddWaitingReadWriteRequest(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);

   KeLockMutex(&DeviceExt->PipeListLock);

   ListEntry = DeviceExt->ThreadListHead.Flink;
   while (ListEntry != &DeviceExt->ThreadListHead)
     {
       ThreadContext = CONTAINING_RECORD(ListEntry, NPFS_THREAD_CONTEXT, ListEntry);
       if (ThreadContext->Count < MAXIMUM_WAIT_OBJECTS)
         {
           break;
         }
       ListEntry = ListEntry->Flink;
     }
   if (ListEntry == &DeviceExt->ThreadListHead)
     {
       ThreadContext = ExAllocatePool(NonPagedPool, sizeof(NPFS_THREAD_CONTEXT));
       if (ThreadContext == NULL)
         {
           KeUnlockMutex(&DeviceExt->PipeListLock);
           return STATUS_NO_MEMORY;
         }
       ThreadContext->DeviceExt = DeviceExt;
       KeInitializeEvent(&ThreadContext->Event, SynchronizationEvent, FALSE);
       ThreadContext->Count = 1;
       ThreadContext->WaitObjectArray[0] = &ThreadContext->Event;


       DPRINT("Creating a new system thread for waiting read/write requests\n");

       Status = PsCreateSystemThread(&hThread,
		                     THREAD_ALL_ACCESS,
				     NULL,
				     NULL,
				     NULL,
				     NpfsWaiterThread,
				     (PVOID)ThreadContext);
       if (!NT_SUCCESS(Status))
         {
           ExFreePool(ThreadContext);
           KeUnlockMutex(&DeviceExt->PipeListLock);
           return Status;
	 }
       InsertHeadList(&DeviceExt->ThreadListHead, &ThreadContext->ListEntry);
       DeviceExt->EmptyWaiterCount += MAXIMUM_WAIT_OBJECTS - 1;
     }
   IoMarkIrpPending(Irp);

   IoAcquireCancelSpinLock(&oldIrql);
   if (Irp->Cancel)
     {
       IoReleaseCancelSpinLock(oldIrql);
       Status = STATUS_CANCELLED;
     }
   else
     {
       (void)IoSetCancelRoutine(Irp, NpfsReadWriteCancelRoutine);
       IoReleaseCancelSpinLock(oldIrql);
       ThreadContext->WaitObjectArray[ThreadContext->Count] = Context->WaitEvent;
       ThreadContext->WaitIrpArray[ThreadContext->Count] = Irp;
       ThreadContext->Count++;
       DeviceExt->EmptyWaiterCount--;
       KeSetEvent(&ThreadContext->Event, IO_NO_INCREMENT, FALSE);
       Status = STATUS_SUCCESS;
     }
   KeUnlockMutex(&DeviceExt->PipeListLock);
   return Status;
}

NTSTATUS STDCALL
NpfsRead(IN PDEVICE_OBJECT DeviceObject,
	 IN PIRP Irp)
{
  PFILE_OBJECT FileObject;
  NTSTATUS Status;
  NTSTATUS OriginalStatus = STATUS_SUCCESS;
  PNPFS_CCB Ccb;
  PNPFS_CONTEXT Context;
  KEVENT Event;
  ULONG Length;
  ULONG Information = 0;
  ULONG CopyLength;
  ULONG TempLength;
  BOOLEAN IsOriginalRequest = TRUE;
  PVOID Buffer;

  DPRINT("NpfsRead(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);

  if (Irp->MdlAddress == NULL)
  {
     DPRINT("Irp->MdlAddress == NULL\n");
     Status = STATUS_UNSUCCESSFUL;
     Irp->IoStatus.Information = 0;
     goto done;
  }

  FileObject = IoGetCurrentIrpStackLocation(Irp)->FileObject;
  Ccb = FileObject->FsContext2;
  Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext;

  if (Ccb->OtherSide == NULL)
  {
     DPRINT("Pipe is NOT connected!\n");
     if (Ccb->PipeState == FILE_PIPE_LISTENING_STATE)
        Status = STATUS_PIPE_LISTENING;
     else if (Ccb->PipeState == FILE_PIPE_DISCONNECTED_STATE)
        Status = STATUS_PIPE_DISCONNECTED;
     else
        Status = STATUS_UNSUCCESSFUL;
     Irp->IoStatus.Information = 0;
     goto done;
  }

  if (Ccb->Data == NULL)
  {
     DPRINT1("Pipe is NOT readable!\n");
     Status = STATUS_UNSUCCESSFUL;
     Irp->IoStatus.Information = 0;
     goto done;
  }

  ExAcquireFastMutex(&Ccb->DataListLock);

  if (IoIsOperationSynchronous(Irp))
  {
     InsertTailList(&Ccb->ReadRequestListHead, &Context->ListEntry);
     if (Ccb->ReadRequestListHead.Flink != &Context->ListEntry)
     {
        KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
	Context->WaitEvent = &Event;
        ExReleaseFastMutex(&Ccb->DataListLock);
        Status = KeWaitForSingleObject(&Event,
	                               Executive,
				       KernelMode,
				       FALSE,
				       NULL);
	if (!NT_SUCCESS(Status))
	{
	   KEBUGCHECK(0);
	}
        ExAcquireFastMutex(&Ccb->DataListLock);
     }
     Irp->IoStatus.Information = 0;
  }
  else
  {
     KIRQL oldIrql;
     if (IsListEmpty(&Ccb->ReadRequestListHead) ||
	 Ccb->ReadRequestListHead.Flink != &Context->ListEntry)
     {
        /* this is a new request */
        Irp->IoStatus.Information = 0;
	Context->WaitEvent = &Ccb->ReadEvent;
        InsertTailList(&Ccb->ReadRequestListHead, &Context->ListEntry);
	if (Ccb->ReadRequestListHead.Flink != &Context->ListEntry)
	{
	   /* there was already a request on the list */
           IoAcquireCancelSpinLock(&oldIrql);
           if (Irp->Cancel)
           {
	      IoReleaseCancelSpinLock(oldIrql);
	      RemoveEntryList(&Context->ListEntry);
	      ExReleaseFastMutex(&Ccb->DataListLock);
	      Status = STATUS_CANCELLED;
	      goto done;
           }
           (void)IoSetCancelRoutine(Irp, NpfsReadWriteCancelRoutine);
           IoReleaseCancelSpinLock(oldIrql);
	   ExReleaseFastMutex(&Ccb->DataListLock);
           IoMarkIrpPending(Irp);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -