PDATA_ENTRY
NpAddDataQueueEntry(
  IN  PDATA_QUEUE DataQueue,
  IN  QUEUE_STATE Who,
  IN  DATA_ENTRY_TYPE Type,
  IN  ULONG DataSize,
  IN  PIRP Irp OPTIONAL,
  IN  PVOID DataPointer OPTIONAL
  );

Routine Description:

    This routine adds a new data entry to the end of the data queue.
    If necessary it will allocate a data entry buffer, or use space in
    the IRP, and possibly complete the indicated IRP.

    The different actions we are perform are based on the type and who
    parameters and quota requirements.

    Type == Internal (i.e, Unbuffered)

        +------+                          - Allocate Data Entry from Irp
        |Irp   |    +----------+
        |      |<---|Unbuffered|          - Reference Irp
        +------+    |InIrp     |
          |         +----------+          - Use system buffer from Irp
          v           |
        +------+      |
        |System|<-----+
        |Buffer|
        +------+

    Type == Buffered && Who == ReadEntries

        +----------+                      - Allocate Data Entry from Irp
        |Irp       |     +-----------+
        |BufferedIo|<----|Buffered   |    - Allocate New System buffer
        |DeallBu...|     |EitherQuota|
        +----------+     +-----------+    - Reference and modify Irp to
          |      |         |                do Buffered I/O, Deallocate
          v      |         v                buffer, and have io completion
        +------+ +------>+------+           copy the buffer (Input operation)
        |User  |         |System|
        |Buffer|         |Buffer|
        +------+         +------+

    Type == Buffered && Who == WriteEntries && PipeQuota Available

        +----------+                      - Allocate Data Entry from Quota
        |Irp       |     +-----------+
        |          |     |Buffered   |    - Allocate New System buffer
        |          |     |PipeQuota  |
        +----------+     +-----------+    - Copy data from User buffer to
          |                |                system buffer
          v                v
        +------+         +------+         - Complete Irp
        |User  |..copy..>|System|
        |Buffer|         |Buffer|
        +------+         +------+

    Type == Buffered && Who == WriteEntries && PipeQuota Not Available

        +----------+                     - Allocate Data Entry from Irp
        |Irp       |     +-----------+
        |BufferedIo|<----|Buffered   |   - Allocate New System buffer
        |DeallBuff |     |UserQuota  |
        +----------+     +-----------+   - Reference and modify Irp to use
          |      |         |               the new system buffer, do Buffered
          v      |         v               I/O, and Deallocate buffer
        +------+ +------>+------+
        |User  |         |System|        - Copy data from User buffer to
        |Buffer|..copy..>|Buffer|          system buffer
        +------+         +------+

    Type == Flush or Close

        +----------+                     - Allocate Data Entry from Irp
        |Irp       |     +-----------+
        |          |<----|Buffered   |   - Reference the Irp
        |          |     |UserQuota  |
        +----------+     +-----------+

Arguments:

    DataQueue - Supplies the Data queue being modified

    Who - Indicates if this is the reader or writer that is adding to the pipe

    Type - Indicates the type of entry to add to the data queue

    DataSize - Indicates the size of the data buffer needed to represent
        this entry

    Irp - Supplies a pointer to the Irp responsible for this entry
        The irp is only optional for buffered write with available pipe quota

    DataPointer - If the Irp is not supplied then this field points to the
        user's write buffer.

Return Value:

    PDATA_ENTRY - Returns a pointer to the newly added data entry