create.c

来自「一个类似windows」· C语言 代码 · 共 766 行 · 第 1/2 页

C
766
字号
     }
   else
     {
       NewPipe = TRUE;
       Pipe = ExAllocatePool(NonPagedPool, sizeof(NPFS_PIPE));
       if (Pipe == NULL)
         {
           KeUnlockMutex(&DeviceExt->PipeListLock);
           Irp->IoStatus.Status = STATUS_NO_MEMORY;
           Irp->IoStatus.Information = 0;
           IoCompleteRequest(Irp, IO_NO_INCREMENT);
           return STATUS_NO_MEMORY;
         }

       Pipe->PipeName.Length = FileObject->FileName.Length;
       Pipe->PipeName.MaximumLength = Pipe->PipeName.Length + sizeof(UNICODE_NULL);
       Pipe->PipeName.Buffer = ExAllocatePool(NonPagedPool, Pipe->PipeName.MaximumLength);
       if (Pipe->PipeName.Buffer == NULL)
         {
           KeUnlockMutex(&DeviceExt->PipeListLock);
           ExFreePool(Pipe);
           ExFreePool(Ccb);
           Irp->IoStatus.Status = STATUS_NO_MEMORY;
           Irp->IoStatus.Information = 0;
           IoCompleteRequest(Irp, IO_NO_INCREMENT);
           return STATUS_NO_MEMORY;
         }

       RtlCopyUnicodeString(&Pipe->PipeName, &FileObject->FileName);

       InitializeListHead(&Pipe->ServerCcbListHead);
       InitializeListHead(&Pipe->ClientCcbListHead);
       InitializeListHead(&Pipe->WaiterListHead);
       KeInitializeMutex(&Pipe->CcbListLock, 0);

       Pipe->PipeType = Buffer->NamedPipeType;
       Pipe->WriteMode = Buffer->ReadMode;
       Pipe->ReadMode = Buffer->ReadMode;
       Pipe->CompletionMode = Buffer->CompletionMode;
       switch (IoStack->Parameters.CreatePipe.ShareAccess & (FILE_SHARE_READ|FILE_SHARE_WRITE))
         {
           case FILE_SHARE_READ:
             Pipe->PipeConfiguration = FILE_PIPE_OUTBOUND;
             break;
           case FILE_SHARE_WRITE:
             Pipe->PipeConfiguration = FILE_PIPE_INBOUND;
             break;
           case FILE_SHARE_READ|FILE_SHARE_WRITE:
             Pipe->PipeConfiguration = FILE_PIPE_FULL_DUPLEX;
             break;
         }
       Pipe->MaximumInstances = Buffer->MaximumInstances;
       Pipe->CurrentInstances = 0;
       Pipe->TimeOut = Buffer->DefaultTimeout;
       if (!(Pipe->PipeConfiguration & FILE_PIPE_OUTBOUND) ||
           Pipe->PipeConfiguration & FILE_PIPE_FULL_DUPLEX)
         {
           if (Buffer->InboundQuota == 0)
             {
               Pipe->InboundQuota = DeviceExt->DefaultQuota;
             }
           else
             {
               Pipe->InboundQuota = PAGE_ROUND_UP(Buffer->InboundQuota);
               if (Pipe->InboundQuota < DeviceExt->MinQuota)
                 {
                   Pipe->InboundQuota = DeviceExt->MinQuota;
                 }
               else if (Pipe->InboundQuota > DeviceExt->MaxQuota)
                 {
                   Pipe->InboundQuota = DeviceExt->MaxQuota;
                 }
             }
         }
       else
         {
           Pipe->InboundQuota = 0;
         }

       if (Pipe->PipeConfiguration & (FILE_PIPE_FULL_DUPLEX|FILE_PIPE_OUTBOUND))
         {
           if (Buffer->OutboundQuota == 0)
             {
               Pipe->OutboundQuota = DeviceExt->DefaultQuota;
             }
           else
             {
               Pipe->OutboundQuota = PAGE_ROUND_UP(Buffer->OutboundQuota);
               if (Pipe->OutboundQuota < DeviceExt->MinQuota)
                 {
                   Pipe->OutboundQuota = DeviceExt->MinQuota;
                 }
               else if (Pipe->OutboundQuota > DeviceExt->MaxQuota)
                 {
                   Pipe->OutboundQuota = DeviceExt->MaxQuota;
                 }
             }
         }
       else
         {
           Pipe->OutboundQuota = 0;
         }

       InsertTailList(&DeviceExt->PipeListHead, &Pipe->PipeListEntry);
       KeUnlockMutex(&DeviceExt->PipeListLock);
     }

   if (Pipe->InboundQuota)
     {
       Ccb->Data = ExAllocatePool(PagedPool, Pipe->InboundQuota);
       if (Ccb->Data == NULL)
         {
           ExFreePool(Ccb);

           if (NewPipe)
             {
               KeLockMutex(&DeviceExt->PipeListLock);
	       RemoveEntryList(&Pipe->PipeListEntry);
               KeUnlockMutex(&DeviceExt->PipeListLock);
               RtlFreeUnicodeString(&Pipe->PipeName);
               ExFreePool(Pipe);
             }

           Irp->IoStatus.Status = STATUS_NO_MEMORY;
           IoCompleteRequest(Irp, IO_NO_INCREMENT);
           return STATUS_NO_MEMORY;
         }
     }
   else
     {
       Ccb->Data = NULL;
     }

   Ccb->ReadPtr = Ccb->Data;
   Ccb->WritePtr = Ccb->Data;
   Ccb->ReadDataAvailable = 0;
   Ccb->WriteQuotaAvailable = Pipe->InboundQuota;
   Ccb->MaxDataLength = Pipe->InboundQuota;
   InitializeListHead(&Ccb->ReadRequestListHead);
   ExInitializeFastMutex(&Ccb->DataListLock);

   Pipe->CurrentInstances++;

   Ccb->Pipe = Pipe;
   Ccb->PipeEnd = FILE_PIPE_SERVER_END;
   Ccb->PipeState = FILE_PIPE_LISTENING_STATE;
   Ccb->OtherSide = NULL;

   DPRINT("CCB: %x\n", Ccb);

   KeInitializeEvent(&Ccb->ConnectEvent, SynchronizationEvent, FALSE);
   KeInitializeEvent(&Ccb->ReadEvent, SynchronizationEvent, FALSE);
   KeInitializeEvent(&Ccb->WriteEvent, SynchronizationEvent, FALSE);

   KeLockMutex(&Pipe->CcbListLock);
   InsertTailList(&Pipe->ServerCcbListHead, &Ccb->CcbListEntry);
   KeUnlockMutex(&Pipe->CcbListLock);

   FileObject->FsContext2 = Ccb;
   FileObject->Flags |= FO_NAMED_PIPE;

   Irp->IoStatus.Status = STATUS_SUCCESS;
   IoCompleteRequest(Irp, IO_NO_INCREMENT);

   DPRINT("Success!\n");

   return STATUS_SUCCESS;
}


NTSTATUS STDCALL
NpfsCleanup(PDEVICE_OBJECT DeviceObject,
	    PIRP Irp)
{
   PNPFS_DEVICE_EXTENSION DeviceExt;
   PIO_STACK_LOCATION IoStack;
   PFILE_OBJECT FileObject;
   PNPFS_CCB Ccb, OtherSide;
   PNPFS_PIPE Pipe;
   BOOLEAN Server;

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

   IoStack = IoGetCurrentIrpStackLocation(Irp);
   DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
   FileObject = IoStack->FileObject;
   Ccb = FileObject->FsContext2;

   if (Ccb == NULL)
   {
      DPRINT("Success!\n");
      Irp->IoStatus.Status = STATUS_SUCCESS;
      Irp->IoStatus.Information = 0;
      IoCompleteRequest(Irp, IO_NO_INCREMENT);
      return STATUS_SUCCESS;
   }

   DPRINT("CCB %p\n", Ccb);
   Pipe = Ccb->Pipe;

   DPRINT("Cleaning pipe %wZ\n", &Pipe->PipeName);

   KeLockMutex(&Pipe->CcbListLock);

   Server = (Ccb->PipeEnd == FILE_PIPE_SERVER_END);

   if (Server)
   {
      /* FIXME: Clean up existing connections here ?? */
      DPRINT("Server\n");
   }
   else
   {
      DPRINT("Client\n");
   }
   if (Ccb->PipeState == FILE_PIPE_CONNECTED_STATE)
   {
      OtherSide = Ccb->OtherSide;
      /* Lock the server first */
      if (Server)
      {
         ExAcquireFastMutex(&Ccb->DataListLock);
	 ExAcquireFastMutex(&OtherSide->DataListLock);
      }
      else
      {
	 ExAcquireFastMutex(&OtherSide->DataListLock);
         ExAcquireFastMutex(&Ccb->DataListLock);
      }
      OtherSide->PipeState = FILE_PIPE_DISCONNECTED_STATE;
      OtherSide->OtherSide = NULL;
      /*
       * Signaling the write event. If is possible that an other
       * thread waits for an empty buffer.
       */
      KeSetEvent(&OtherSide->ReadEvent, IO_NO_INCREMENT, FALSE);
      KeSetEvent(&OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE);
      if (Server)
      {
         ExReleaseFastMutex(&OtherSide->DataListLock);
         ExReleaseFastMutex(&Ccb->DataListLock);
      }
      else
      {
          ExReleaseFastMutex(&Ccb->DataListLock);
          ExReleaseFastMutex(&OtherSide->DataListLock);
      }
   }
   else if (Ccb->PipeState == FILE_PIPE_LISTENING_STATE)
   {
      PLIST_ENTRY Entry;
      PNPFS_WAITER_ENTRY WaitEntry = NULL;
      BOOLEAN Complete = FALSE;
      KIRQL oldIrql;
      PIRP tmpIrp;

      Entry = Ccb->Pipe->WaiterListHead.Flink;
      while (Entry != &Ccb->Pipe->WaiterListHead)
      {
         WaitEntry = CONTAINING_RECORD(Entry, NPFS_WAITER_ENTRY, Entry);
	 if (WaitEntry->Ccb == Ccb)
	 {
            RemoveEntryList(Entry);
	    tmpIrp = CONTAINING_RECORD(WaitEntry, IRP, Tail.Overlay.DriverContext);
	    IoAcquireCancelSpinLock(&oldIrql);
	    if (!tmpIrp->Cancel)
	    {
               (void)IoSetCancelRoutine(tmpIrp, NULL);
	       Complete = TRUE;
	    }
	    IoReleaseCancelSpinLock(oldIrql);
            if (Complete)
	    {
	       tmpIrp->IoStatus.Status = STATUS_PIPE_BROKEN;
               tmpIrp->IoStatus.Information = 0;
               IoCompleteRequest(tmpIrp, IO_NO_INCREMENT);
	    }
	    break;
	 }
	 Entry = Entry->Flink;
      }

   }
   Ccb->PipeState = FILE_PIPE_CLOSING_STATE;

   KeUnlockMutex(&Pipe->CcbListLock);

   ExAcquireFastMutex(&Ccb->DataListLock);
   if (Ccb->Data)
   {
      ExFreePool(Ccb->Data);
      Ccb->Data = NULL;
      Ccb->ReadPtr = NULL;
      Ccb->WritePtr = NULL;
   }
   ExReleaseFastMutex(&Ccb->DataListLock);

   Irp->IoStatus.Status = STATUS_SUCCESS;
   Irp->IoStatus.Information = 0;
   IoCompleteRequest(Irp, IO_NO_INCREMENT);

   DPRINT("Success!\n");

   return STATUS_SUCCESS;
}

NTSTATUS STDCALL
NpfsClose(PDEVICE_OBJECT DeviceObject,
          PIRP Irp)
{
   PNPFS_DEVICE_EXTENSION DeviceExt;
   PIO_STACK_LOCATION IoStack;
   PFILE_OBJECT FileObject;
   PNPFS_CCB Ccb;
   PNPFS_PIPE Pipe;
   BOOLEAN Server;

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

   IoStack = IoGetCurrentIrpStackLocation(Irp);
   DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
   FileObject = IoStack->FileObject;
   Ccb = FileObject->FsContext2;

   if (Ccb == NULL)
   {
      DPRINT("Success!\n");
      Irp->IoStatus.Status = STATUS_SUCCESS;
      Irp->IoStatus.Information = 0;
      IoCompleteRequest(Irp, IO_NO_INCREMENT);
      return STATUS_SUCCESS;
   }

   DPRINT("CCB %x\n", Ccb);
   Pipe = Ccb->Pipe;

   DPRINT("Closing pipe %wZ\n", &Pipe->PipeName);

   KeLockMutex(&Pipe->CcbListLock);

   Server = (Ccb->PipeEnd == FILE_PIPE_SERVER_END);

   if (Server)
   {
      DPRINT("Server\n");
      Pipe->CurrentInstances--;
   }
   else
   {
      DPRINT("Client\n");
   }

   ASSERT(Ccb->PipeState == FILE_PIPE_CLOSING_STATE);

   FileObject->FsContext2 = NULL;

   RemoveEntryList(&Ccb->CcbListEntry);

   ExFreePool(Ccb);

   KeUnlockMutex(&Pipe->CcbListLock);

   if (IsListEmpty(&Pipe->ServerCcbListHead) &&
       IsListEmpty(&Pipe->ClientCcbListHead))
   {
      RtlFreeUnicodeString(&Pipe->PipeName);
      KeLockMutex(&DeviceExt->PipeListLock);
      RemoveEntryList(&Pipe->PipeListEntry);
      KeUnlockMutex(&DeviceExt->PipeListLock);
      ExFreePool(Pipe);
   }

   Irp->IoStatus.Status = STATUS_SUCCESS;
   Irp->IoStatus.Information = 0;
   IoCompleteRequest(Irp, IO_NO_INCREMENT);

   DPRINT("Success!\n");

   return STATUS_SUCCESS;
}

/* EOF */

⌨️ 快捷键说明

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