[FASTFAT] Start implementing FAT32 statistics support
[reactos.git] / drivers / filesystems / npfs / 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 // File ID number for NPFS bugchecking support
14 #define NPFS_BUGCHECK_FILE_ID (NPFS_BUGCHECK_WRITESUP)
15
16 /* FUNCTIONS ******************************************************************/
17
18 NTSTATUS
19 NTAPI
20 NpWriteDataQueue(IN PNP_DATA_QUEUE WriteQueue,
21 IN ULONG Mode,
22 IN PVOID OutBuffer,
23 IN ULONG OutBufferSize,
24 IN ULONG PipeType,
25 OUT PULONG BytesNotWritten,
26 IN PNP_CCB Ccb,
27 IN ULONG NamedPipeEnd,
28 IN PETHREAD Thread,
29 IN PLIST_ENTRY List)
30 {
31 BOOLEAN HaveContext = FALSE, MoreProcessing, AllocatedBuffer;
32 PNP_DATA_QUEUE_ENTRY DataEntry;
33 ULONG DataSize, BufferSize;
34 PIRP WriteIrp;
35 PIO_STACK_LOCATION IoStack;
36 PVOID Buffer;
37 NTSTATUS Status;
38 PSECURITY_CLIENT_CONTEXT ClientContext;
39 PAGED_CODE();
40
41 *BytesNotWritten = OutBufferSize;
42
43 MoreProcessing = TRUE;
44 if ((PipeType != FILE_PIPE_MESSAGE_MODE) || (OutBufferSize))
45 {
46 MoreProcessing = FALSE;
47 }
48
49 for (DataEntry = CONTAINING_RECORD(NpGetNextRealDataQueueEntry(WriteQueue, List),
50 NP_DATA_QUEUE_ENTRY,
51 QueueEntry);
52 ((WriteQueue->QueueState == ReadEntries) &&
53 ((*BytesNotWritten > 0) || (MoreProcessing)));
54 DataEntry = CONTAINING_RECORD(NpGetNextRealDataQueueEntry(WriteQueue, List),
55 NP_DATA_QUEUE_ENTRY,
56 QueueEntry))
57 {
58 DataSize = DataEntry->DataSize;
59
60 IoStack = IoGetCurrentIrpStackLocation(DataEntry->Irp);
61
62 if (IoStack->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL &&
63 IoStack->Parameters.FileSystemControl.FsControlCode == FSCTL_PIPE_INTERNAL_READ_OVFLOW &&
64 (DataSize < OutBufferSize || MoreProcessing))
65 {
66 WriteIrp = NpRemoveDataQueueEntry(WriteQueue, TRUE, List);
67 if (WriteIrp)
68 {
69 WriteIrp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
70 InsertTailList(List, &WriteIrp->Tail.Overlay.ListEntry);
71 }
72 continue;
73 }
74
75 if (DataEntry->DataEntryType == Unbuffered)
76 {
77 DataEntry->Irp->Overlay.AllocationSize.QuadPart = 0;
78 }
79
80 BufferSize = *BytesNotWritten;
81 if (BufferSize >= DataSize) BufferSize = DataSize;
82
83 if (DataEntry->DataEntryType != Unbuffered && BufferSize)
84 {
85 Buffer = ExAllocatePoolWithTag(NonPagedPool, BufferSize, NPFS_DATA_ENTRY_TAG);
86 if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES;
87 AllocatedBuffer = TRUE;
88 }
89 else
90 {
91 Buffer = DataEntry->Irp->AssociatedIrp.SystemBuffer;
92 AllocatedBuffer = FALSE;
93 }
94
95 _SEH2_TRY
96 {
97 RtlCopyMemory(Buffer,
98 (PVOID)((ULONG_PTR)OutBuffer + OutBufferSize - *BytesNotWritten),
99 BufferSize);
100 }
101 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
102 {
103 if (AllocatedBuffer) ExFreePool(Buffer);
104 _SEH2_YIELD(return _SEH2_GetExceptionCode());
105 }
106 _SEH2_END;
107
108 if (!HaveContext)
109 {
110 HaveContext = TRUE;
111 Status = NpGetClientSecurityContext(NamedPipeEnd, Ccb, Thread, &ClientContext);
112 if (!NT_SUCCESS(Status))
113 {
114 if (AllocatedBuffer) ExFreePool(Buffer);
115 return Status;
116 }
117
118 if (ClientContext)
119 {
120 NpFreeClientSecurityContext(Ccb->ClientContext);
121 Ccb->ClientContext = ClientContext;
122 }
123 }
124
125 WriteIrp = NpRemoveDataQueueEntry(WriteQueue, TRUE, List);
126 if (WriteIrp)
127 {
128 *BytesNotWritten -= BufferSize;
129 WriteIrp->IoStatus.Information = BufferSize;
130
131 if (AllocatedBuffer)
132 {
133 WriteIrp->AssociatedIrp.SystemBuffer = Buffer;
134 WriteIrp->Flags |= IRP_DEALLOCATE_BUFFER | IRP_BUFFERED_IO | IRP_INPUT_OPERATION;
135 }
136
137 if (!*BytesNotWritten)
138 {
139 MoreProcessing = FALSE;
140 WriteIrp->IoStatus.Status = STATUS_SUCCESS;
141 InsertTailList(List, &WriteIrp->Tail.Overlay.ListEntry);
142 continue;
143 }
144
145 if (Mode == FILE_PIPE_MESSAGE_MODE)
146 {
147 WriteIrp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
148 }
149 else
150 {
151 WriteIrp->IoStatus.Status = STATUS_SUCCESS;
152 }
153
154 InsertTailList(List, &WriteIrp->Tail.Overlay.ListEntry);
155 }
156 else if (AllocatedBuffer)
157 {
158 ExFreePool(Buffer);
159 }
160 }
161
162 if (*BytesNotWritten > 0 || MoreProcessing)
163 {
164 ASSERT(WriteQueue->QueueState != ReadEntries);
165 Status = STATUS_MORE_PROCESSING_REQUIRED;
166 }
167 else
168 {
169 Status = STATUS_SUCCESS;
170 }
171
172 return Status;
173 }
174
175 /* EOF */