Sync up with trunk r61578.
[reactos.git] / drivers / filesystems / npfs / write.c
1 /*
2 * PROJECT: ReactOS Named Pipe FileSystem
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/filesystems/npfs/write.c
5 * PURPOSE: Pipes Writing
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include "npfs.h"
12
13 // File ID number for NPFS bugchecking support
14 #define NPFS_BUGCHECK_FILE_ID (NPFS_BUGCHECK_WRITE)
15
16 /* GLOBALS ********************************************************************/
17
18 LONG NpSlowWriteCalls;
19
20 /* FUNCTIONS ******************************************************************/
21
22 BOOLEAN
23 NTAPI
24 NpCommonWrite(IN PFILE_OBJECT FileObject,
25 IN PVOID Buffer,
26 IN ULONG DataSize,
27 IN PETHREAD Thread,
28 IN PIO_STATUS_BLOCK IoStatus,
29 IN PIRP Irp,
30 IN PLIST_ENTRY List)
31 {
32 NODE_TYPE_CODE NodeType;
33 BOOLEAN WriteOk;
34 PNP_CCB Ccb;
35 PNP_NONPAGED_CCB NonPagedCcb;
36 PNP_DATA_QUEUE WriteQueue;
37 NTSTATUS Status;
38 PNP_EVENT_BUFFER EventBuffer;
39 ULONG BytesWritten, NamedPipeEnd, ReadMode;
40 PAGED_CODE();
41
42 IoStatus->Information = 0;
43 NodeType = NpDecodeFileObject(FileObject, NULL, &Ccb, &NamedPipeEnd);
44
45 if (!NodeType)
46 {
47 IoStatus->Status = STATUS_PIPE_DISCONNECTED;
48 return TRUE;
49 }
50
51 if (NodeType != NPFS_NTC_CCB)
52 {
53 IoStatus->Status = STATUS_INVALID_PARAMETER;
54 return TRUE;
55 }
56
57 NonPagedCcb = Ccb->NonPagedCcb;
58 ExAcquireResourceExclusiveLite(&NonPagedCcb->Lock, TRUE);
59
60 if (Ccb->NamedPipeState != FILE_PIPE_CONNECTED_STATE)
61 {
62 if (Ccb->NamedPipeState == FILE_PIPE_DISCONNECTED_STATE)
63 {
64 IoStatus->Status = STATUS_PIPE_DISCONNECTED;
65 }
66 else if (Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE)
67 {
68 IoStatus->Status = STATUS_PIPE_LISTENING;
69 }
70 else
71 {
72 ASSERT(Ccb->NamedPipeState == FILE_PIPE_CLOSING_STATE);
73 IoStatus->Status = STATUS_PIPE_CLOSING;
74 }
75
76 WriteOk = TRUE;
77 goto Quickie;
78 }
79
80 if ((NamedPipeEnd == FILE_PIPE_SERVER_END && Ccb->Fcb->NamedPipeConfiguration == FILE_PIPE_INBOUND) ||
81 (NamedPipeEnd == FILE_PIPE_CLIENT_END && Ccb->Fcb->NamedPipeConfiguration == FILE_PIPE_OUTBOUND))
82 {
83 IoStatus->Status = STATUS_INVALID_PARAMETER;
84 WriteOk = TRUE;
85 goto Quickie;
86 }
87
88 IoStatus->Status = STATUS_SUCCESS;
89 IoStatus->Information = DataSize;
90
91 if (NamedPipeEnd == FILE_PIPE_SERVER_END)
92 {
93 WriteQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
94 ReadMode = Ccb->ReadMode[FILE_PIPE_CLIENT_END];
95 }
96 else
97 {
98 WriteQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
99 ReadMode = Ccb->ReadMode[FILE_PIPE_SERVER_END];
100 }
101
102 EventBuffer = NonPagedCcb->EventBuffer[NamedPipeEnd];
103
104 if ((WriteQueue->QueueState == ReadEntries &&
105 WriteQueue->BytesInQueue < DataSize &&
106 WriteQueue->Quota < DataSize - WriteQueue->BytesInQueue) ||
107 (WriteQueue->QueueState == ReadEntries &&
108 WriteQueue->Quota - WriteQueue->QuotaUsed < DataSize))
109 {
110 if (Ccb->Fcb->NamedPipeType == FILE_PIPE_MESSAGE_TYPE &&
111 Ccb->CompletionMode[NamedPipeEnd] == FILE_PIPE_COMPLETE_OPERATION)
112 {
113 IoStatus->Information = 0;
114 IoStatus->Status = STATUS_SUCCESS;
115 WriteOk = TRUE;
116 goto Quickie;
117 }
118
119 if (!Irp)
120 {
121 WriteOk = FALSE;
122 goto Quickie;
123 }
124 }
125
126 Status = NpWriteDataQueue(WriteQueue,
127 ReadMode,
128 Buffer,
129 DataSize,
130 Ccb->Fcb->NamedPipeType,
131 &BytesWritten,
132 Ccb,
133 NamedPipeEnd,
134 Thread,
135 List);
136 IoStatus->Status = Status;
137
138 if (Status == STATUS_MORE_PROCESSING_REQUIRED)
139 {
140 ASSERT(WriteQueue->QueueState != ReadEntries);
141 if ((Ccb->CompletionMode[NamedPipeEnd] == FILE_PIPE_COMPLETE_OPERATION || !Irp) &&
142 ((WriteQueue->Quota - WriteQueue->QuotaUsed) < BytesWritten))
143 {
144 IoStatus->Information = DataSize - BytesWritten;
145 IoStatus->Status = STATUS_SUCCESS;
146 }
147 else
148 {
149 ASSERT(WriteQueue->QueueState != ReadEntries);
150
151 IoStatus->Status = NpAddDataQueueEntry(NamedPipeEnd,
152 Ccb,
153 WriteQueue,
154 WriteEntries,
155 Buffered,
156 DataSize,
157 Irp,
158 Buffer,
159 DataSize - BytesWritten);
160 }
161 }
162
163 if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
164 WriteOk = TRUE;
165
166 Quickie:
167 ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
168 return WriteOk;
169 }
170
171 NTSTATUS
172 NTAPI
173 NpFsdWrite(IN PDEVICE_OBJECT DeviceObject,
174 IN PIRP Irp)
175 {
176 PIO_STACK_LOCATION IoStack;
177 IO_STATUS_BLOCK IoStatus;
178 LIST_ENTRY DeferredList;
179 PAGED_CODE();
180 NpSlowWriteCalls++;
181
182 InitializeListHead(&DeferredList);
183 IoStack = IoGetCurrentIrpStackLocation(Irp);
184
185 FsRtlEnterFileSystem();
186 NpAcquireSharedVcb();
187
188 NpCommonWrite(IoStack->FileObject,
189 Irp->UserBuffer,
190 IoStack->Parameters.Write.Length,
191 Irp->Tail.Overlay.Thread,
192 &IoStatus,
193 Irp,
194 &DeferredList);
195
196 NpReleaseVcb();
197 NpCompleteDeferredIrps(&DeferredList);
198 FsRtlExitFileSystem();
199
200 if (IoStatus.Status != STATUS_PENDING)
201 {
202 Irp->IoStatus.Information = IoStatus.Information;
203 Irp->IoStatus.Status = IoStatus.Status;
204 IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
205 }
206
207 return IoStatus.Status;
208 }
209
210 /* EOF */