master
cpp 800 lines 17.9 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 lxbusclient.cpp
8
9 Abstract:
10
11 This file contains the LxBus client library implementation.
12
13 --*/
14
15 #include "precomp.h"
16
17 NTSTATUS
18 LxBusClientpIoctlInternal(
19 _In_ HANDLE Handle,
20 _In_opt_ HANDLE Event,
21 _Inout_ PIO_STATUS_BLOCK IoStatusBlock,
22 _In_ ULONG ControlCode,
23 _In_reads_bytes_(InputBufferSize) PVOID InputBuffer,
24 _In_ ULONG InputBufferSize,
25 _Out_writes_bytes_(OutputBufferSize) PVOID OutputBuffer,
26 _In_ ULONG OutputBufferSize);
27
28 NTSTATUS
29 LxBusClientCreateUnnamedServer(_In_ HANDLE MessagePortHandle, _Out_ PLXBUS_IPC_MESSAGE_CREATE_UNNAMED_SERVER_PARAMETERS Parameters)
30
31 /*++
32
33 Routine Description:
34
35 This routine creates an unnamed server with an LxBus message port.
36
37 Arguments:
38
39 MessagePortHandle - Supplies a handle to a message port.
40
41 Parameters - Supplies a pointer to the create unnamed server parameters.
42
43 Return Value:
44
45 NT status code.
46
47 --*/
48
49 {
50 return LxBusClientpIoctl(MessagePortHandle, LXBUS_IPC_MESSAGE_IOCTL_CREATE_UNNAMED_SERVER, NULL, 0, Parameters, sizeof(*Parameters));
51 }
52
53 NTSTATUS
54 LxBusClientDisconnectConsole(_In_ HANDLE MessagePortHandle, _Inout_ PLXBUS_IPC_MESSAGE_DISCONNECT_CONSOLE_PARAMETERS Parameters)
55
56 /*++
57
58 Routine Description:
59
60 This routine sends a disconnect console ioctl to the specified message port
61 handle.
62
63 Arguments:
64
65 MessagePortHandle - Supplies a handle to the message port to issue the
66 ioctl to.
67
68 Parameters - Supplies a pointer to the disconnect console parameters.
69
70 Return Value:
71
72 NT status code.
73
74 --*/
75
76 {
77 return LxBusClientpIoctl(MessagePortHandle, LXBUS_IPC_MESSAGE_IOCTL_DISCONNECT_CONSOLE, Parameters, sizeof(*Parameters), NULL, 0);
78 }
79
80 NTSTATUS
81 LxBusClientMarshalConsole(_In_ HANDLE MessagePortHandle, _Inout_ PLXBUS_IPC_MESSAGE_MARSHAL_CONSOLE_PARAMETERS Parameters)
82
83 /*++
84
85 Routine Description:
86
87 This routine sends a marshal console ioctl to the specified message port
88 handle.
89
90 Arguments:
91
92 MessagePortHandle - Supplies a handle to the message port to issue the
93 ioctl to.
94
95 Parameters - Supplies a pointer to the marshal console parameters.
96
97 Return Value:
98
99 NT status code.
100
101 --*/
102
103 {
104 return LxBusClientpIoctl(
105 MessagePortHandle, LXBUS_IPC_MESSAGE_IOCTL_MARSHAL_CONSOLE, Parameters, sizeof(*Parameters), Parameters, sizeof(*Parameters));
106 }
107
108 NTSTATUS
109 LxBusClientReleaseConsole(_In_ HANDLE MessagePortHandle, _In_ PLXBUS_IPC_MESSAGE_IOCTL_CANCEL_MARSHAL_PARAMETERS Parameters)
110
111 /*++
112
113 Routine Description:
114
115 This routine sends a cleanup console ioctl to the specified message port
116 handle.
117
118 Arguments:
119
120 MessagePortHandle - Supplies a handle to the message port to issue the
121 ioctl to.
122
123 Parameters - Supplies a pointer to the release console parameters.
124
125 Return Value:
126
127 NT status code.
128
129 --*/
130
131 {
132 return LxBusClientpIoctl(MessagePortHandle, LXBUS_IPC_MESSAGE_IOCTL_CANCEL_MARSHAL, Parameters, sizeof(*Parameters), NULL, 0);
133 }
134
135 NTSTATUS
136 LxBusClientMarshalForkToken(_In_ HANDLE MessagePortHandle, _Inout_ PLXBUS_IPC_MESSAGE_MARSHAL_FORK_TOKEN_PARAMETERS Parameters)
137
138 /*++
139
140 Routine Description:
141
142 This routine sends a marshal fork token ioctl to the specified message port
143 handle.
144
145 Arguments:
146
147 MessagePortHandle - Supplies a handle to the message port to issue the
148 ioctl to.
149
150 Parameters - Supplies a pointer to the marshal fork token parameters.
151
152 Return Value:
153
154 NT status code.
155
156 --*/
157
158 {
159 return LxBusClientpIoctl(
160 MessagePortHandle, LXBUS_IPC_MESSAGE_IOCTL_MARSHAL_FORK_TOKEN, Parameters, sizeof(*Parameters), Parameters, sizeof(*Parameters));
161 }
162
163 NTSTATUS
164 LxBusClientReleaseForkToken(_In_ HANDLE MessagePortHandle, _In_ PLXBUS_IPC_MESSAGE_IOCTL_CANCEL_MARSHAL_PARAMETERS Parameters)
165
166 /*++
167
168 Routine Description:
169
170 This routine sends a cleanup fork token ioctl to the specified message port
171 handle.
172
173 Arguments:
174
175 MessagePortHandle - Supplies a handle to the message port to issue the
176 ioctl to.
177
178 Parameters - Supplies a pointer to the release fork token parameters.
179
180 Return Value:
181
182 NT status code.
183
184 --*/
185
186 {
187 return LxBusClientpIoctl(MessagePortHandle, LXBUS_IPC_MESSAGE_IOCTL_CANCEL_MARSHAL, Parameters, sizeof(*Parameters), NULL, 0);
188 }
189
190 NTSTATUS
191 LxBusClientMarshalHandle(_In_ HANDLE MessagePortHandle, _Inout_ PLXBUS_IPC_MESSAGE_MARSHAL_HANDLE_PARAMETERS Parameters)
192
193 /*++
194
195 Routine Description:
196
197 This routine sends a marshal handle ioctl to the specified message port
198 handle.
199
200 Arguments:
201
202 MessagePortHandle - Supplies a handle to the message port to issue the
203 ioctl to.
204
205 Parameters - Supplies a pointer to the marshal handle parameters.
206
207 Return Value:
208
209 NT status code.
210
211 --*/
212
213 {
214 return LxBusClientpIoctl(
215 MessagePortHandle, LXBUS_IPC_MESSAGE_IOCTL_MARSHAL_HANDLE, Parameters, sizeof(*Parameters), Parameters, sizeof(*Parameters));
216 }
217
218 NTSTATUS
219 LxBusClientReleaseHandle(_In_ HANDLE MessagePortHandle, _In_ PLXBUS_IPC_MESSAGE_IOCTL_CANCEL_MARSHAL_PARAMETERS Parameters)
220
221 /*++
222
223 Routine Description:
224
225 This routine sends a cleanup handle ioctl to the specified message port
226 handle.
227
228 Arguments:
229
230 MessagePortHandle - Supplies a handle to the message port to issue the
231 ioctl to.
232
233 Parameters - Supplies a pointer to the release handle parameters.
234
235 Return Value:
236
237 NT status code.
238
239 --*/
240
241 {
242 return LxBusClientpIoctl(MessagePortHandle, LXBUS_IPC_MESSAGE_IOCTL_CANCEL_MARSHAL, Parameters, sizeof(*Parameters), NULL, 0);
243 }
244
245 NTSTATUS
246 LxBusClientMarshalProcess(_In_ HANDLE MessagePortHandle, _Inout_ PLXBUS_IPC_MESSAGE_MARSHAL_PROCESS_PARAMETERS Parameters)
247
248 /*++
249
250 Routine Description:
251
252 This routine sends a marshal process ioctl to the specified message port
253 handle.
254
255 Arguments:
256
257 MessagePortHandle - Supplies a handle to the message port to issue the
258 ioctl to.
259
260 Parameters - Supplies a pointer to the marshal process parameters.
261
262 Return Value:
263
264 NT status code.
265
266 --*/
267
268 {
269 return LxBusClientpIoctl(
270 MessagePortHandle, LXBUS_IPC_MESSAGE_IOCTL_MARSHAL_PROCESS, Parameters, sizeof(*Parameters), Parameters, sizeof(*Parameters));
271 }
272
273 NTSTATUS
274 LxBusClientpIoctl(
275 _In_ HANDLE Handle,
276 _In_ ULONG ControlCode,
277 _In_reads_bytes_(InputBufferSize) PVOID InputBuffer,
278 _In_ ULONG InputBufferSize,
279 _Out_writes_bytes_(OutputBufferSize) PVOID OutputBuffer,
280 _In_ ULONG OutputBufferSize)
281
282 /*++
283
284 Routine Description:
285
286 This routine implements the lxbus control device IOCTL handler.
287
288 Arguments:
289
290 Handle - Supplies the handle to issue the ioctl to.
291
292 ControlCode - Supplies ioctl to be processed.
293
294 InputBuffer - Supplies the input buffer as passed by user.
295
296 InputBufferSize - Supplies the size of the input buffer.
297
298 OutputBuffer - Supplies a output buffer as passed by the user.
299
300 OutputBufferSize - Supplies the size of the output buffer.
301
302 Return Value:
303
304 NT status code.
305
306 --*/
307
308 {
309 NTSTATUS Status;
310 IO_STATUS_BLOCK IoStatus;
311
312 ZeroMemory(&IoStatus, sizeof(IoStatus));
313 Status = LxBusClientpIoctlInternal(Handle, NULL, &IoStatus, ControlCode, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize);
314
315 WI_ASSERT(Status != STATUS_PENDING);
316
317 WI_ASSERT(!NT_SUCCESS(Status) || (OutputBufferSize == IoStatus.Information));
318
319 return Status;
320 }
321
322 NTSTATUS
323 LxBusClientpIoctlInternal(
324 _In_ HANDLE Handle,
325 _In_opt_ HANDLE Event,
326 _Inout_ PIO_STATUS_BLOCK IoStatus,
327 _In_ ULONG ControlCode,
328 _In_reads_bytes_(InputBufferSize) PVOID InputBuffer,
329 _In_ ULONG InputBufferSize,
330 _Out_writes_bytes_(OutputBufferSize) PVOID OutputBuffer,
331 _In_ ULONG OutputBufferSize)
332
333 /*++
334
335 Routine Description:
336
337 This routine implements the lxbus control device IOCTL handler.
338
339 Arguments:
340
341 Handle - Supplies the handle to issue the ioctl to.
342
343 Event - Supplies an optional event used for async IO.
344
345 IoStatus - Supplies a pointer to the IO status block.
346
347 ControlCode - Supplies ioctl to be processed.
348
349 InputBuffer - Supplies the input buffer as passed by user.
350
351 InputBufferSize - Supplies the size of the input buffer.
352
353 OutputBuffer - Supplies a output buffer as passed by the user.
354
355 OutputBufferSize - Supplies the size of the output buffer.
356
357 Return Value:
358
359 NT status code.
360
361 --*/
362
363 {
364 NTSTATUS Status;
365
366 if (Handle == NULL)
367 {
368 Status = STATUS_DEVICE_NOT_CONNECTED;
369 goto LxBusClientpIoctlInternalEnd;
370 }
371
372 Status = NtDeviceIoControlFile(Handle, Event, NULL, NULL, IoStatus, ControlCode, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize);
373
374 LxBusClientpIoctlInternalEnd:
375 return Status;
376 }
377
378 NTSTATUS
379 LxBusClientReceiveMessage(_In_ HANDLE MessagePortHandle, _Out_writes_to_(BufferSize, *SizeReceived) PVOID Buffer, _In_ ULONG BufferSize, _Out_ PULONG SizeReceived)
380
381 /*++
382
383 Routine Description:
384
385 This routine receives a message from the given message port synchronously.
386
387 Arguments:
388
389 MessagePortHandle - Supplies a handle to a message port.
390
391 Buffer - Supplies a pointer to a buffer.
392
393 BufferSize - Supplies the size of the buffer in bytes.
394
395 SizeReceived - Supplies a buffer to store the number of bytes received.
396
397 Return Value:
398
399 NT status code.
400
401 --*/
402
403 {
404 HANDLE Event;
405 IO_STATUS_BLOCK IoStatus;
406 NTSTATUS Status;
407
408 Event = NULL;
409 RtlZeroMemory(&IoStatus, sizeof(IoStatus));
410 Status = ZwCreateEvent(&Event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE);
411
412 if (!NT_SUCCESS(Status))
413 {
414 goto LxBusClientReceiveMessageEnd;
415 }
416
417 Status = LxBusClientReceiveMessageAsync(MessagePortHandle, Buffer, BufferSize, SizeReceived, &IoStatus, Event);
418
419 if (!NT_SUCCESS(Status))
420 {
421 goto LxBusClientReceiveMessageEnd;
422 }
423
424 if (Status == STATUS_PENDING)
425 {
426 Status = NtWaitForSingleObject(Event, FALSE, NULL);
427 if (!NT_SUCCESS(Status))
428 {
429 goto LxBusClientReceiveMessageEnd;
430 }
431 }
432
433 WI_ASSERT(NT_SUCCESS(Status));
434
435 WI_ASSERT(IoStatus.Information <= ULONG_MAX);
436
437 *SizeReceived = (ULONG)IoStatus.Information;
438 Status = IoStatus.Status;
439
440 LxBusClientReceiveMessageEnd:
441 if (Event != NULL)
442 {
443 NtClose(Event);
444 }
445
446 return Status;
447 }
448
449 NTSTATUS
450 LxBusClientReceiveMessageAsync(
451 _In_ HANDLE MessagePortHandle,
452 _Out_writes_bytes_to_(BufferSize, *SizeReceived) PVOID Buffer,
453 _In_ ULONG BufferSize,
454 _Out_ PULONG SizeReceived,
455 _Out_ PIO_STATUS_BLOCK IoStatus,
456 _Inout_opt_ HANDLE Event)
457
458 /*++
459
460 Routine Description:
461
462 This routine receives a message from the given message port asynchronously.
463
464 Arguments:
465
466 MessagePortHandle - Supplies a handle to a message port.
467
468 Buffer - Supplies a pointer to a buffer.
469
470 BufferSize - Supplies the size of the buffer in bytes.
471
472 SizeReceived - Supplies a buffer to store the number of bytes received.
473
474 IoStatus - Supplies a pointer to an io status block.
475
476 Event - Supplies an optional event to be signaled when the operation is
477 complete.
478
479 Return Value:
480
481 NT status code.
482
483 --*/
484
485 {
486 LARGE_INTEGER ByteOffset{};
487 const NTSTATUS Status = NtReadFile(MessagePortHandle, Event, NULL, NULL, IoStatus, Buffer, BufferSize, &ByteOffset, NULL);
488 if (Status == STATUS_SUCCESS)
489 {
490 WI_ASSERT(IoStatus->Information <= ULONG_MAX);
491
492 *SizeReceived = (ULONG)IoStatus->Information;
493 }
494
495 return Status;
496 }
497
498 NTSTATUS
499 LxBusClientRegisterServer(_In_ HANDLE LxBusHandle, _Inout_ PLXBUS_REGISTER_SERVER_PARAMETERS Parameters)
500
501 /*++
502
503 Routine Description:
504
505 This routine registers an LxBus server with the given name.
506
507 Arguments:
508
509 LxBusHandle - The LxBusHandle on which to perform the registration.
510
511 Parameters - Supplies a pointer to the register server parameters.
512
513 Return Value:
514
515 NT status code.
516
517 --*/
518
519 {
520 return LxBusClientpIoctl(LxBusHandle, LXBUS_IOCTL_REGISTER_SERVER, Parameters, sizeof(*Parameters), Parameters, sizeof(*Parameters));
521 }
522
523 NTSTATUS
524 LxBusClientRegisterUserCallbackAsync(
525 _In_ HANDLE LxBusHandle,
526 _In_ HANDLE Event,
527 _Inout_ PIO_STATUS_BLOCK IoStatus,
528 _Inout_ PLXBUS_REGISTER_USER_CALLBACK_PARAMETERS Parameters,
529 _Out_ PVOID OutputBuffer,
530 _In_ ULONG OutputBufferSize)
531
532 /*++
533
534 Routine Description:
535
536 This routine sends a user-callback registration ioctl to the specified
537 instance handle.
538
539 Arguments:
540
541 LxBusHandle - Supplies ths instance handle to issue the ioctl to.
542
543 Event - Supplies an event to be signalled when the request has completed.
544
545 IoStatus - Supplies a pointer to the IO status block.
546
547 Parameters - Supplies a pointer to the user callback parameters.
548
549 OutputBuffer - Supplies a pointer to the output buffer.
550
551 OutputBufferSize - Supplies the size in bytes of the output buffer.
552
553 Return Value:
554
555 NT status code.
556
557 --*/
558
559 {
560 return LxBusClientpIoctlInternal(
561 LxBusHandle, Event, IoStatus, LXBUS_IOCTL_REGISTER_USER_CALLBACK, Parameters, sizeof(*Parameters), OutputBuffer, OutputBufferSize);
562 }
563
564 NTSTATUS
565 LxBusClientSendMessage(_In_ HANDLE MessagePortHandle, _In_reads_bytes_(BufferSize) PVOID Buffer, _In_ ULONG BufferSize)
566
567 /*++
568
569 Routine Description:
570
571 This routine sends a message to the given message port synchronously.
572
573 Arguments:
574
575 MessagePortHandle - Supplies a handle to a message port.
576
577 Buffer - Supplies a pointer to a buffer.
578
579 BufferSize - Supplies the size of the buffer in bytes.
580
581 Return Value:
582
583 NT status code.
584
585 --*/
586
587 {
588 HANDLE Event;
589 IO_STATUS_BLOCK IoStatus;
590 NTSTATUS Status;
591
592 Event = NULL;
593 RtlZeroMemory(&IoStatus, sizeof(IoStatus));
594 Status = ZwCreateEvent(&Event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE);
595
596 if (!NT_SUCCESS(Status))
597 {
598 goto LxBusClientSendMessageEnd;
599 }
600
601 Status = LxBusClientSendMessageAsync(MessagePortHandle, Buffer, BufferSize, &IoStatus, Event);
602
603 if (!NT_SUCCESS(Status))
604 {
605 goto LxBusClientSendMessageEnd;
606 }
607
608 WI_ASSERT((Status != STATUS_SUCCESS) || (BufferSize == IoStatus.Information));
609
610 if (Status == STATUS_PENDING)
611 {
612 Status = NtWaitForSingleObject(Event, FALSE, NULL);
613 if (!NT_SUCCESS(Status))
614 {
615 goto LxBusClientSendMessageEnd;
616 }
617 }
618
619 Status = IoStatus.Status;
620
621 LxBusClientSendMessageEnd:
622 if (Event != NULL)
623 {
624 NtClose(Event);
625 }
626
627 return Status;
628 }
629
630 NTSTATUS
631 LxBusClientSendMessageAsync(
632 _In_ HANDLE MessagePortHandle, _In_reads_bytes_(BufferSize) PVOID Buffer, _In_ ULONG BufferSize, _Out_ PIO_STATUS_BLOCK IoStatus, _Inout_opt_ HANDLE Event)
633
634 /*++
635
636 Routine Description:
637
638 This routine sends a message to the given message port asynchronously.
639
640 Arguments:
641
642 MessagePortHandle - Supplies a handle to a message port.
643
644 Buffer - Supplies a pointer to a buffer.
645
646 BufferSize - Supplies the size of the buffer in bytes.
647
648 IoStatus - Supplies a pointer to an io status block.
649
650 Event - Supplies an optional event to be signaled when the operation is
651 complete.
652
653 Return Value:
654
655 NT status code.
656
657 --*/
658
659 {
660 LARGE_INTEGER ByteOffset{};
661 const NTSTATUS Status = NtWriteFile(MessagePortHandle, Event, NULL, NULL, IoStatus, Buffer, BufferSize, &ByteOffset, NULL);
662
663 WI_ASSERT((Status != STATUS_SUCCESS) || (BufferSize == IoStatus->Information));
664
665 return Status;
666 }
667
668 NTSTATUS
669 LxBusClientUnmarshalProcess(_In_ HANDLE MessagePortHandle, _Inout_ PLXBUS_IPC_MESSAGE_UNMARSHAL_PROCESS_PARAMETERS Parameters)
670
671 /*++
672
673 Routine Description:
674
675 This routine sends a unmarshal process ioctl to the specified message port
676 handle.
677
678 Arguments:
679
680 MessagePortHandle - Supplies a handle to the message port to issue the
681 ioctl to.
682
683 Parameters - Supplies a pointer to the unmarshal process parameters.
684
685 Return Value:
686
687 NT status code.
688
689 --*/
690
691 {
692 return LxBusClientpIoctl(
693 MessagePortHandle, LXBUS_IPC_MESSAGE_IOCTL_UNMARSHAL_PROCESS, Parameters, sizeof(*Parameters), Parameters, sizeof(*Parameters));
694 }
695
696 NTSTATUS
697 LxBusClientUnmarshalVfsFile(_In_ HANDLE MessagePortHandle, _Inout_ PLXBUS_IPC_MESSAGE_UNMARSHAL_VFS_FILE_PARAMETERS Parameters)
698
699 /*++
700
701 Routine Description:
702
703 This routine sends a unmarshal vfs file ioctl to the specified message port
704 handle.
705
706 Arguments:
707
708 MessagePortHandle - Supplies a handle to the message port to issue the
709 ioctl to.
710
711 Parameters - Supplies a pointer to the unmarshal vfs file parameters.
712
713 Return Value:
714
715 NT status code.
716
717 --*/
718
719 {
720 return LxBusClientpIoctl(
721 MessagePortHandle, LXBUS_IPC_MESSAGE_IOCTL_UNMARSHAL_VFS_FILE, Parameters, sizeof(*Parameters), Parameters, sizeof(*Parameters));
722 }
723
724 NTSTATUS
725 LxBusClientUserCallbackSendResponse(_In_ HANDLE LxBusHandle, _Inout_ PLXBUS_REGISTER_USER_CALLBACK_PARAMETERS Parameters)
726
727 /*++
728
729 Routine Description:
730
731 This routine sends a response from a user-callback to the specified
732 instance handle.
733
734 Arguments:
735
736 LxBusHandle - Supplies ths instance handle to issue the ioctl to.
737
738 Parameters - Supplies a pointer to the user callback parameters.
739
740 Return Value:
741
742 NT status code.
743
744 --*/
745
746 {
747 return LxBusClientpIoctl(LxBusHandle, LXBUS_IOCTL_REGISTER_USER_CALLBACK, Parameters, sizeof(*Parameters), NULL, 0);
748 }
749
750 NTSTATUS
751 LxBusClientWaitForConnection(_In_ HANDLE ServerPortHandle, _Out_ PLXBUS_IPC_SERVER_WAIT_FOR_CONNECTION_PARAMETERS Parameters)
752
753 /*++
754
755 Routine Description:
756
757 Waits for a client connection on the provided server port.
758
759 Arguments:
760
761 ServerPortHandle - Supplies a handle to the server port.
762
763 Parameters - Supplies a pointer to the wait for connection parameters.
764
765 Return Value:
766
767 NT status code.
768
769 --*/
770
771 {
772 return LxBusClientpIoctl(
773 ServerPortHandle, LXBUS_IPC_SERVER_IOCTL_WAIT_FOR_CONNECTION, Parameters, sizeof(*Parameters), Parameters, sizeof(*Parameters));
774 }
775
776 NTSTATUS
777 LxBusClientWaitForLxProcess(_In_ HANDLE LxProcessHandle, _Out_ PLXBUS_IPC_LX_PROCESS_WAIT_FOR_TERMINATION_PARAMETERS Parameters)
778
779 /*++
780
781 Routine Description:
782
783 Waits for a client connection on the provided server port.
784
785 Arguments:
786
787 LxProcessHandle - Supplies a handle to the LX process.
788
789 Parameters - Supplies a pointer to the wait for termination parameters.
790
791 Return Value:
792
793 NT status code.
794
795 --*/
796
797 {
798 return LxBusClientpIoctl(
799 LxProcessHandle, LXBUS_IPC_LX_PROCESS_IOCTL_WAIT_FOR_TERMINATION, Parameters, sizeof(*Parameters), Parameters, sizeof(*Parameters));
800 }