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