1fd7d4dbb7230ef97293ed6b121e19a6a1bde439
[reactos.git] / reactos / drivers / filesystems / npfs_new / writesup.c
1 /*
2 * PROJECT: ReactOS Named Pipe FileSystem
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/filesystems/npfs/writesup.c
5 * PURPOSE: Pipes Writing Support
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include "npfs.h"
12
13 /* FUNCTIONS ******************************************************************/
14
15 NTSTATUS
16 NTAPI
17 NpWriteDataQueue(IN PNP_DATA_QUEUE WriteQueue,
18 IN ULONG Mode,
19 IN PVOID OutBuffer,
20 IN ULONG OutBufferSize,
21 IN ULONG PipeType,
22 OUT PULONG BytesNotWritten,
23 IN PNP_CCB Ccb,
24 IN ULONG NamedPipeEnd,
25 IN PETHREAD Thread,
26 IN PLIST_ENTRY List)
27 {
28 BOOLEAN HaveContext = FALSE, MoreProcessing, AllocatedBuffer;
29 PNP_DATA_QUEUE_ENTRY DataEntry;
30 ULONG DataSize, BufferSize;
31 PIRP WriteIrp;
32 PIO_STACK_LOCATION IoStack;
33 PVOID Buffer;
34 NTSTATUS Status;
35 PSECURITY_CLIENT_CONTEXT ClientContext;
36 PAGED_CODE();
37
38 *BytesNotWritten = OutBufferSize;
39
40 MoreProcessing = TRUE;
41 if ((PipeType != FILE_PIPE_MESSAGE_MODE) || (OutBufferSize))
42 {
43 MoreProcessing = FALSE;
44 }
45
46 for (DataEntry = NpGetNextRealDataQueueEntry(WriteQueue, List);
47 ((WriteQueue->QueueState == ReadEntries) &&
48 ((*BytesNotWritten > 0) || (MoreProcessing)));
49 DataEntry = NpGetNextRealDataQueueEntry(WriteQueue, List))
50 {
51 DataSize = DataEntry->DataSize;
52
53 IoStack = IoGetCurrentIrpStackLocation( DataEntry->Irp);
54
55 if (IoStack->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL &&
56 IoStack->Parameters.FileSystemControl.FsControlCode == FSCTL_PIPE_INTERNAL_READ_OVFLOW &&
57 (DataSize < OutBufferSize || MoreProcessing))
58 {
59 WriteIrp = NpRemoveDataQueueEntry(WriteQueue, TRUE, List);
60 if (WriteIrp)
61 {
62 WriteIrp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
63 InsertTailList(List, &WriteIrp->Tail.Overlay.ListEntry);
64 }
65 continue;
66 }
67
68 if (DataEntry->DataEntryType == Unbuffered)
69 {
70 DataEntry->Irp->Overlay.AllocationSize.QuadPart = 0;
71 }
72
73 BufferSize = *BytesNotWritten;
74 if (BufferSize >= DataSize) BufferSize = DataSize;
75
76 if (DataEntry->DataEntryType != Unbuffered && BufferSize)
77 {
78 Buffer = ExAllocatePoolWithTag(NonPagedPool, BufferSize, NPFS_DATA_ENTRY_TAG);
79 if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES;
80 AllocatedBuffer = TRUE;
81 }
82 else
83 {
84 Buffer = DataEntry->Irp->AssociatedIrp.SystemBuffer;
85 AllocatedBuffer = FALSE;
86 }
87
88 _SEH2_TRY
89 {
90 RtlCopyMemory(Buffer,
91 (PVOID)((ULONG_PTR)OutBuffer + OutBufferSize - *BytesNotWritten),
92 BufferSize);
93 }
94 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
95 {
96 if (AllocatedBuffer) ExFreePool(Buffer);
97 return _SEH2_GetExceptionCode();
98 }
99 _SEH2_END;
100
101 if (!HaveContext)
102 {
103 HaveContext = TRUE;
104 Status = NpGetClientSecurityContext(NamedPipeEnd, Ccb, Thread, &ClientContext);
105 if (!NT_SUCCESS(Status))
106 {
107 if (AllocatedBuffer) ExFreePool(Buffer);
108 return Status;
109 }
110
111 if (ClientContext)
112 {
113 NpFreeClientSecurityContext(Ccb->ClientContext);
114 Ccb->ClientContext = ClientContext;
115 }
116 }
117
118 WriteIrp = NpRemoveDataQueueEntry(WriteQueue, TRUE, List);
119 if (WriteIrp)
120 {
121 *BytesNotWritten -= BufferSize;
122 WriteIrp->IoStatus.Information = BufferSize;
123
124 if (AllocatedBuffer)
125 {
126 WriteIrp->AssociatedIrp.SystemBuffer = Buffer;
127 WriteIrp->Flags |= IRP_DEALLOCATE_BUFFER | IRP_BUFFERED_IO | IRP_INPUT_OPERATION;
128 }
129
130 if (!*BytesNotWritten)
131 {
132 MoreProcessing = FALSE;
133 WriteIrp->IoStatus.Status = STATUS_SUCCESS;
134 InsertTailList(List, &WriteIrp->Tail.Overlay.ListEntry);
135 continue;
136 }
137
138 if (Mode == FILE_PIPE_MESSAGE_MODE)
139 {
140 WriteIrp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
141 }
142 else
143 {
144 WriteIrp->IoStatus.Status = STATUS_SUCCESS;
145 }
146
147 InsertTailList(List, &WriteIrp->Tail.Overlay.ListEntry);
148 }
149 else if (AllocatedBuffer)
150 {
151 ExFreePool(Buffer);
152 }
153 }
154
155 if (*BytesNotWritten > 0 || MoreProcessing)
156 {
157 ASSERT(WriteQueue->QueueState != ReadEntries);
158 Status = STATUS_MORE_PROCESSING_REQUIRED;
159 }
160 else
161 {
162 Status = STATUS_SUCCESS;
163 }
164
165 return Status;
166 }
167
168 /* EOF */