finished applying @implemented and @unimplemented comments and remove the comments...
[reactos.git] / reactos / ntoskrnl / io / iocomp.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ke/iocomp.c
5 * PURPOSE:
6 * PROGRAMMER: David Welch (welch@mcmail.com)
7 * UPDATE HISTORY:
8 * Created 22/05/98
9 Changed NtQueryIoCompletion
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <limits.h>
15 #define NTOS_MODE_KERNEL
16 #include <ntos.h>
17 //#include <ntos/synch.h>
18
19 #define NDEBUG
20 #include <internal/debug.h>
21
22 #define IOC_TAG TAG('I', 'O', 'C', 'T')
23
24 POBJECT_TYPE ExIoCompletionType;
25
26 NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside;
27
28 static GENERIC_MAPPING ExIoCompletionMapping =
29 {
30 STANDARD_RIGHTS_READ | IO_COMPLETION_QUERY_STATE,
31 STANDARD_RIGHTS_WRITE | IO_COMPLETION_MODIFY_STATE,
32 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | IO_COMPLETION_QUERY_STATE,
33 IO_COMPLETION_ALL_ACCESS
34 };
35
36 /* FUNCTIONS *****************************************************************/
37
38 NTSTATUS
39 STDCALL
40 NtpCreateIoCompletion(
41 PVOID ObjectBody,
42 PVOID Parent,
43 PWSTR RemainingPath,
44 POBJECT_ATTRIBUTES ObjectAttributes
45 )
46 {
47 DPRINT("NtpCreateIoCompletion(ObjectBody %x, Parent %x, RemainingPath %S)\n",
48 ObjectBody, Parent, RemainingPath);
49
50 if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
51 {
52 return STATUS_UNSUCCESSFUL;
53 }
54
55 return STATUS_SUCCESS;
56 }
57
58 VOID STDCALL
59 NtpDeleteIoCompletion(PVOID ObjectBody)
60 {
61 PKQUEUE Queue = ObjectBody;
62
63 DPRINT("NtpDeleteIoCompletion()\n");
64
65 KeRundownQueue(Queue);
66 }
67
68
69 VOID
70 NtInitializeIoCompletionImplementation(VOID)
71 {
72 ExIoCompletionType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
73
74 RtlCreateUnicodeString(&ExIoCompletionType->TypeName, L"IoCompletion");
75
76 ExIoCompletionType->Tag = IOC_TAG;
77 ExIoCompletionType->MaxObjects = ULONG_MAX;
78 ExIoCompletionType->MaxHandles = ULONG_MAX;
79 ExIoCompletionType->TotalObjects = 0;
80 ExIoCompletionType->TotalHandles = 0;
81 ExIoCompletionType->PagedPoolCharge = 0;
82 ExIoCompletionType->NonpagedPoolCharge = sizeof(KQUEUE);
83 ExIoCompletionType->Mapping = &ExIoCompletionMapping;
84 ExIoCompletionType->Dump = NULL;
85 ExIoCompletionType->Open = NULL;
86 ExIoCompletionType->Close = NULL;
87 ExIoCompletionType->Delete = NtpDeleteIoCompletion;
88 ExIoCompletionType->Parse = NULL;
89 ExIoCompletionType->Security = NULL;
90 ExIoCompletionType->QueryName = NULL;
91 ExIoCompletionType->OkayToClose = NULL;
92 ExIoCompletionType->Create = NtpCreateIoCompletion;
93 ExIoCompletionType->DuplicationNotify = NULL;
94
95 ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside,
96 NULL,
97 NULL,
98 0,
99 sizeof(IO_COMPLETION_PACKET),
100 IOC_TAG,
101 0);
102 }
103
104
105 NTSTATUS
106 STDCALL
107 NtCreateIoCompletion(
108 OUT PHANDLE IoCompletionHandle,
109 IN ACCESS_MASK DesiredAccess,
110 IN POBJECT_ATTRIBUTES ObjectAttributes,
111 IN ULONG NumberOfConcurrentThreads
112 )
113 {
114 PKQUEUE Queue;
115 NTSTATUS Status;
116
117 Status = ObRosCreateObject(IoCompletionHandle,
118 DesiredAccess,
119 ObjectAttributes,
120 ExIoCompletionType,
121 (PVOID*)&Queue);
122
123 if (NT_SUCCESS(Status))
124 {
125 (void) KeInitializeQueue(Queue, NumberOfConcurrentThreads);
126 ObDereferenceObject(Queue);
127 }
128
129 return Status;
130 /*
131
132 CompletionPort = NULL OR ExistingCompletionPort
133
134 */
135
136
137 }
138
139 /*
140 DesiredAccess:
141 ZERO
142 IO_COMPLETION_QUERY_STATE Query access
143 IO_COMPLETION_MODIFY_STATE Modify access
144 IO_COMPLETION_ALL_ACCESS All of the preceding + STANDARD_RIGHTS_ALL
145
146 ObjectAttributes
147 OBJ_OPENLINK and OBJ_PERMANENT are not valid attributes
148
149 Return Value
150 STATUS_SUCCESS or an error status, such as STATUS_ACCESS_DENIED or
151 STATUS_OBJECT_NAME_NOT_FOUND.
152 */
153 NTSTATUS
154 STDCALL
155 NtOpenIoCompletion(
156 OUT PHANDLE IoCompletionHandle,
157 IN ACCESS_MASK DesiredAccess,
158 IN POBJECT_ATTRIBUTES ObjectAttributes
159 )
160 {
161 NTSTATUS Status;
162
163 Status = ObOpenObjectByName(ObjectAttributes,
164 ExIoCompletionType,
165 NULL,
166 UserMode,
167 DesiredAccess,
168 NULL,
169 IoCompletionHandle); //<- ???
170
171 return Status;
172 }
173
174
175 NTSTATUS
176 STDCALL
177 NtQueryIoCompletion(
178 IN HANDLE IoCompletionHandle,
179 IN IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass,
180 OUT PVOID IoCompletionInformation,
181 IN ULONG IoCompletionInformationLength,
182 OUT PULONG ResultLength OPTIONAL
183 )
184 {
185 PKQUEUE Queue;
186 NTSTATUS Status;
187
188 if (IoCompletionInformationClass != IoCompletionBasicInformation)
189 {
190 return STATUS_INVALID_INFO_CLASS;
191 }
192 if (IoCompletionInformationLength < sizeof(IO_COMPLETION_BASIC_INFORMATION))
193 {
194 return STATUS_INFO_LENGTH_MISMATCH;
195 }
196
197 Status = ObReferenceObjectByHandle( IoCompletionHandle,
198 IO_COMPLETION_QUERY_STATE,
199 ExIoCompletionType,
200 UserMode,
201 (PVOID*)&Queue,
202 NULL);
203 if (NT_SUCCESS(Status))
204 {
205 ((PIO_COMPLETION_BASIC_INFORMATION)IoCompletionInformation)->SignalState =
206 Queue->Header.SignalState;
207
208 ObDereferenceObject(Queue);
209
210 if (ResultLength) *ResultLength = sizeof(IO_COMPLETION_BASIC_INFORMATION);
211 }
212
213 return Status;
214 }
215
216
217 /*
218 * Dequeues an I/O completion message from an I/O completion object
219 */
220 NTSTATUS
221 STDCALL
222 NtRemoveIoCompletion(
223 IN HANDLE IoCompletionHandle,
224 OUT PULONG CompletionKey,
225 OUT PULONG CompletionValue,
226 OUT PIO_STATUS_BLOCK IoStatusBlock,
227 IN PLARGE_INTEGER Timeout OPTIONAL
228 )
229 {
230 PKQUEUE Queue;
231 NTSTATUS Status;
232
233 Status = ObReferenceObjectByHandle( IoCompletionHandle,
234 IO_COMPLETION_MODIFY_STATE,
235 ExIoCompletionType,
236 UserMode,
237 (PVOID*)&Queue,
238 NULL);
239 if (NT_SUCCESS(Status))
240 {
241 PIO_COMPLETION_PACKET Packet;
242 PLIST_ENTRY ListEntry;
243
244 /*
245 Try 2 remove packet from queue. Wait (optionaly) if
246 no packet in queue or max num of threads allready running.
247 */
248 ListEntry = KeRemoveQueue(Queue, UserMode, Timeout );
249
250 ObDereferenceObject(Queue);
251
252 Packet = CONTAINING_RECORD(ListEntry, IO_COMPLETION_PACKET, ListEntry);
253
254 if (CompletionKey) *CompletionKey = Packet->Key;
255 if (CompletionValue) *CompletionValue = Packet->Overlapped;
256 if (IoStatusBlock) *IoStatusBlock = Packet->IoStatus;
257
258 ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside, Packet);
259 }
260
261 return Status;
262 }
263
264
265 /*
266 ASSOSIERT MED FOB's IoCompletionContext
267
268 typedef struct _IO_COMPLETION_CONTEXT {
269 PVOID Port;
270 ULONG Key;
271 } IO_COMPLETION_CONTEXT, *PIO_COMPLETION_CONTEXT;
272
273 */
274
275
276 /*
277 * Queues an I/O completion message to an I/O completion object
278 */
279 NTSTATUS
280 STDCALL
281 NtSetIoCompletion(
282 IN HANDLE IoCompletionPortHandle,
283 IN ULONG CompletionKey,
284 IN ULONG CompletionValue,
285 IN NTSTATUS CompletionStatus,
286 IN ULONG CompletionInformation
287 )
288 {
289 NTSTATUS Status;
290 PKQUEUE Queue;
291
292 Status = ObReferenceObjectByHandle( IoCompletionPortHandle,
293 IO_COMPLETION_MODIFY_STATE,
294 ExIoCompletionType,
295 UserMode,
296 (PVOID*)&Queue,
297 NULL);
298 if (NT_SUCCESS(Status))
299 {
300 PIO_COMPLETION_PACKET Packet;
301
302 Packet = ExAllocateFromNPagedLookasideList(&IoCompletionPacketLookaside);
303
304 Packet->Key = CompletionKey;
305 Packet->Overlapped = CompletionValue;
306 Packet->IoStatus.Status = CompletionStatus;
307 Packet->IoStatus.Information = CompletionInformation;
308
309 KeInsertQueue(Queue, &Packet->ListEntry);
310 ObDereferenceObject(Queue);
311 }
312
313 return Status;
314 }