fixed some signed/unsigned comparison warnings with -Wsign-compare
[reactos.git] / reactos / ntoskrnl / io / file.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/file.c
5 * PURPOSE: I/O File Object & NT File Handle Access/Managment of Files.
6 *
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
8 * David Welch (welch@mcmail.com)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* GLOBALS *******************************************************************/
18
19 extern GENERIC_MAPPING IopFileMapping;
20
21 NTSTATUS
22 STDCALL
23 SeSetWorldSecurityDescriptor(SECURITY_INFORMATION SecurityInformation,
24 PSECURITY_DESCRIPTOR SecurityDescriptor,
25 PULONG BufferLength);
26
27 /* INTERNAL FUNCTIONS ********************************************************/
28
29 /*
30 * NAME INTERNAL
31 * IopCreateFile
32 *
33 * DESCRIPTION
34 *
35 * ARGUMENTS
36 *
37 * RETURN VALUE
38 *
39 * REVISIONS
40 */
41 NTSTATUS
42 STDCALL
43 IopCreateFile(PVOID ObjectBody,
44 PVOID Parent,
45 PWSTR RemainingPath,
46 POBJECT_CREATE_INFORMATION ObjectCreateInfo)
47 {
48 PDEVICE_OBJECT DeviceObject;
49 PFILE_OBJECT FileObject = (PFILE_OBJECT) ObjectBody;
50 POBJECT_TYPE ParentObjectType;
51 NTSTATUS Status;
52
53 DPRINT("IopCreateFile(ObjectBody 0x%p, Parent 0x%p, RemainingPath %S)\n",
54 ObjectBody,
55 Parent,
56 RemainingPath);
57
58 if (NULL == Parent)
59 {
60 /* This is probably an attempt to create a meta fileobject (eg. for FAT)
61 for the cache manager, so return STATUS_SUCCESS */
62 DPRINT("Parent object was NULL\n");
63 return(STATUS_SUCCESS);
64 }
65
66 ParentObjectType = BODY_TO_HEADER(Parent)->Type;
67
68 if (ParentObjectType != IoDeviceObjectType &&
69 ParentObjectType != IoFileObjectType)
70 {
71 DPRINT("Parent [%wZ] is a %S which is neither a file type nor a device type ; remaining path = %S\n",
72 &HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(Parent))->Name,
73 BODY_TO_HEADER(Parent)->Type->Name.Buffer,
74 RemainingPath);
75 return(STATUS_UNSUCCESSFUL);
76 }
77
78 Status = ObReferenceObjectByPointer(Parent,
79 STANDARD_RIGHTS_REQUIRED,
80 ParentObjectType,
81 UserMode);
82 if (!NT_SUCCESS(Status))
83 {
84 CPRINT("Failed to reference parent object 0x%p\n", Parent);
85 return(Status);
86 }
87
88 if (ParentObjectType == IoDeviceObjectType)
89 {
90 /* Parent is a devce object */
91 DeviceObject = IoGetAttachedDevice((PDEVICE_OBJECT)Parent);
92 DPRINT("DeviceObject 0x%p\n", DeviceObject);
93
94 if (RemainingPath == NULL)
95 {
96 FileObject->Flags = FileObject->Flags | FO_DIRECT_DEVICE_OPEN;
97 FileObject->FileName.Buffer = 0;
98 FileObject->FileName.Length = FileObject->FileName.MaximumLength = 0;
99 }
100 else
101 {
102 if ((DeviceObject->DeviceType != FILE_DEVICE_FILE_SYSTEM)
103 && (DeviceObject->DeviceType != FILE_DEVICE_DISK)
104 && (DeviceObject->DeviceType != FILE_DEVICE_CD_ROM)
105 && (DeviceObject->DeviceType != FILE_DEVICE_TAPE)
106 && (DeviceObject->DeviceType != FILE_DEVICE_NETWORK)
107 && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE)
108 && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT))
109 {
110 CPRINT("Device was wrong type\n");
111 return(STATUS_UNSUCCESSFUL);
112 }
113
114 if (DeviceObject->DeviceType != FILE_DEVICE_NETWORK
115 && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE)
116 && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT))
117 {
118 if (!(DeviceObject->Vpb->Flags & VPB_MOUNTED))
119 {
120 DPRINT("Mount the logical volume\n");
121 Status = IoMountVolume(DeviceObject, FALSE);
122 DPRINT("Status %x\n", Status);
123 if (!NT_SUCCESS(Status))
124 {
125 CPRINT("Failed to mount logical volume (Status %x)\n", Status);
126 return(Status);
127 }
128 }
129 DeviceObject = DeviceObject->Vpb->DeviceObject;
130 DPRINT("FsDeviceObject %lx\n", DeviceObject);
131 }
132 RtlpCreateUnicodeString(&(FileObject->FileName),
133 RemainingPath, NonPagedPool);
134 }
135 }
136 else
137 {
138 /* Parent is a file object */
139 if (RemainingPath == NULL)
140 {
141 CPRINT("Device is unnamed\n");
142 return STATUS_UNSUCCESSFUL;
143 }
144
145 DeviceObject = ((PFILE_OBJECT)Parent)->DeviceObject;
146 DPRINT("DeviceObject 0x%p\n", DeviceObject);
147
148 FileObject->RelatedFileObject = (PFILE_OBJECT)Parent;
149
150 RtlpCreateUnicodeString(&(FileObject->FileName),
151 RemainingPath, NonPagedPool);
152 }
153
154 DPRINT("FileObject->FileName %wZ\n",
155 &FileObject->FileName);
156 FileObject->DeviceObject = DeviceObject;
157 DPRINT("FileObject 0x%p DeviceObject 0x%p\n",
158 FileObject,
159 DeviceObject);
160 FileObject->Vpb = DeviceObject->Vpb;
161 FileObject->Type = IO_TYPE_FILE;
162
163 return(STATUS_SUCCESS);
164 }
165
166 VOID
167 STDCALL
168 IopDeleteFile(PVOID ObjectBody)
169 {
170 PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody;
171 PIRP Irp;
172 PIO_STACK_LOCATION StackPtr;
173 NTSTATUS Status;
174 KEVENT Event;
175 PDEVICE_OBJECT DeviceObject;
176
177 DPRINT("IopDeleteFile()\n");
178
179 if (FileObject->DeviceObject)
180 {
181 /* Check if this is a direct open or not */
182 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
183 {
184 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
185 }
186 else
187 {
188 DeviceObject = IoGetRelatedDeviceObject(FileObject);
189 }
190
191 /* Clear and set up Events */
192 KeClearEvent(&FileObject->Event);
193 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
194
195 /* Allocate an IRP */
196 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
197
198 /* Set it up */
199 Irp->UserEvent = &Event;
200 Irp->UserIosb = &Irp->IoStatus;
201 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
202 Irp->Tail.Overlay.OriginalFileObject = FileObject;
203 Irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API;
204
205 /* Set up Stack Pointer Data */
206 StackPtr = IoGetNextIrpStackLocation(Irp);
207 StackPtr->MajorFunction = IRP_MJ_CLOSE;
208 StackPtr->DeviceObject = DeviceObject;
209 StackPtr->FileObject = FileObject;
210
211 /* Call the FS Driver */
212 Status = IoCallDriver(DeviceObject, Irp);
213
214 /* Wait for completion */
215 if (Status == STATUS_PENDING)
216 {
217 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
218 }
219 IoFreeIrp(Irp);
220
221 }
222
223 /* Clear the file name */
224 if (FileObject->FileName.Buffer)
225 {
226 ExFreePool(FileObject->FileName.Buffer);
227 FileObject->FileName.Buffer = NULL;
228 }
229
230 /* Free the completion context */
231 if (FileObject->CompletionContext)
232 {
233 ObDereferenceObject(FileObject->CompletionContext->Port);
234 ExFreePool(FileObject->CompletionContext);
235 }
236 }
237
238 NTSTATUS
239 STDCALL
240 IopSecurityFile(PVOID ObjectBody,
241 SECURITY_OPERATION_CODE OperationCode,
242 SECURITY_INFORMATION SecurityInformation,
243 PSECURITY_DESCRIPTOR SecurityDescriptor,
244 PULONG BufferLength)
245 {
246 IO_STATUS_BLOCK IoStatusBlock;
247 PIO_STACK_LOCATION StackPtr;
248 PFILE_OBJECT FileObject;
249 PDEVICE_OBJECT DeviceObject;
250 ULONG MajorFunction;
251 PIRP Irp;
252 BOOLEAN LocalEvent = FALSE;
253 KEVENT Event;
254 NTSTATUS Status = STATUS_SUCCESS;
255
256 DPRINT("IopSecurityFile() called\n");
257
258 FileObject = (PFILE_OBJECT)ObjectBody;
259
260 if (OperationCode == QuerySecurityDescriptor)
261 {
262 MajorFunction = IRP_MJ_QUERY_SECURITY;
263 DPRINT("Query security descriptor\n");
264 }
265 else if (OperationCode == DeleteSecurityDescriptor)
266 {
267 DPRINT("Delete\n");
268 return STATUS_SUCCESS;
269 }
270 else if (OperationCode == AssignSecurityDescriptor)
271 {
272 /* If this is a direct open, we can assign it */
273 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
274 {
275 /* Get the Device Object */
276 DPRINT("here\n");
277 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
278
279 /* Assign the Security Descriptor */
280 DeviceObject->SecurityDescriptor = SecurityDescriptor;
281 }
282 return STATUS_SUCCESS;
283 }
284 else
285 {
286 MajorFunction = IRP_MJ_SET_SECURITY;
287 DPRINT("Set security descriptor\n");
288
289 /* If this is a direct open, we can set it */
290 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
291 {
292 DPRINT1("Set SD unimplemented for Devices\n");
293 return STATUS_SUCCESS;
294 }
295 }
296
297 /* Get the Device Object */
298 DPRINT1("FileObject: %p\n", FileObject);
299 DeviceObject = IoGetRelatedDeviceObject(FileObject);
300
301 /* Check if we should use Sync IO or not */
302 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
303 {
304 /* Use File Object event */
305 KeClearEvent(&FileObject->Event);
306 }
307 else
308 {
309 /* Use local event */
310 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
311 LocalEvent = TRUE;
312 }
313
314 /* Allocate the IRP */
315 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
316
317 /* Set the IRP */
318 Irp->Tail.Overlay.OriginalFileObject = FileObject;
319 Irp->RequestorMode = ExGetPreviousMode();
320 Irp->UserIosb = &IoStatusBlock;
321 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
322 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
323 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
324
325 /* Set Stack Parameters */
326 StackPtr = IoGetNextIrpStackLocation(Irp);
327 StackPtr->FileObject = FileObject;
328
329 /* Set Parameters */
330 if (OperationCode == QuerySecurityDescriptor)
331 {
332 StackPtr->Parameters.QuerySecurity.SecurityInformation = SecurityInformation;
333 StackPtr->Parameters.QuerySecurity.Length = *BufferLength;
334 Irp->UserBuffer = SecurityDescriptor;
335 }
336 else
337 {
338 StackPtr->Parameters.SetSecurity.SecurityInformation = SecurityInformation;
339 StackPtr->Parameters.SetSecurity.SecurityDescriptor = SecurityDescriptor;
340 }
341
342 ObReferenceObject(FileObject);
343
344 /* Call the Driver */
345 Status = IoCallDriver(FileObject->DeviceObject, Irp);
346
347 if (Status == STATUS_PENDING)
348 {
349 if (LocalEvent)
350 {
351 KeWaitForSingleObject(&Event,
352 Executive,
353 KernelMode,
354 FileObject->Flags & FO_ALERTABLE_IO,
355 NULL);
356 Status = IoStatusBlock.Status;
357 }
358 else
359 {
360 KeWaitForSingleObject(&FileObject->Event,
361 Executive,
362 KernelMode,
363 FileObject->Flags & FO_ALERTABLE_IO,
364 NULL);
365 Status = FileObject->FinalStatus;
366 }
367 }
368
369 /* This Driver doesn't implement Security, so try to give it a default */
370 if (Status == STATUS_INVALID_DEVICE_REQUEST)
371 {
372 if (OperationCode == QuerySecurityDescriptor)
373 {
374 /* Set a World Security Descriptor */
375 Status = SeSetWorldSecurityDescriptor(SecurityInformation,
376 SecurityDescriptor,
377 BufferLength);
378 }
379 else
380 {
381 /* It wasn't a query, so just fake success */
382 Status = STATUS_SUCCESS;
383 }
384 }
385 else if (OperationCode == QuerySecurityDescriptor)
386 {
387 /* Return length */
388 *BufferLength = IoStatusBlock.Information;
389 }
390
391 /* Return Status */
392 return Status;
393 }
394
395 NTSTATUS
396 STDCALL
397 IopQueryNameFile(PVOID ObjectBody,
398 POBJECT_NAME_INFORMATION ObjectNameInfo,
399 ULONG Length,
400 PULONG ReturnLength)
401 {
402 POBJECT_NAME_INFORMATION LocalInfo;
403 PFILE_OBJECT FileObject;
404 ULONG LocalReturnLength;
405 NTSTATUS Status;
406
407 DPRINT1("IopQueryNameFile() called\n");
408
409 FileObject = (PFILE_OBJECT)ObjectBody;
410
411 /* Allocate Buffer */
412 LocalInfo = ExAllocatePool(PagedPool,
413 sizeof(OBJECT_NAME_INFORMATION) +
414 MAX_PATH * sizeof(WCHAR));
415 if (LocalInfo == NULL) return STATUS_INSUFFICIENT_RESOURCES;
416
417 /* Query the name */
418 Status = ObQueryNameString(FileObject->DeviceObject,
419 LocalInfo,
420 MAX_PATH * sizeof(WCHAR),
421 &LocalReturnLength);
422 if (!NT_SUCCESS (Status))
423 {
424 ExFreePool (LocalInfo);
425 return Status;
426 }
427 DPRINT ("Device path: %wZ\n", &LocalInfo->Name);
428
429 /* Write Device Path */
430 Status = RtlAppendUnicodeStringToString(&ObjectNameInfo->Name,
431 &(LocalInfo)->Name);
432
433 /* Query the File name */
434 Status = IoQueryFileInformation(FileObject,
435 FileNameInformation,
436 LocalReturnLength,
437 LocalInfo,
438 NULL);
439 if (Status != STATUS_SUCCESS)
440 {
441 ExFreePool(LocalInfo);
442 return Status;
443 }
444
445 /* Write the Name */
446 Status = RtlAppendUnicodeToString(&ObjectNameInfo->Name,
447 ((PFILE_NAME_INFORMATION)LocalInfo)->FileName);
448 DPRINT ("Total path: %wZ\n", &ObjectNameInfo->Name);
449
450 /* Free buffer and return */
451 ExFreePool(LocalInfo);
452 return Status;
453 }
454
455 VOID
456 STDCALL
457 IopCloseFile(PVOID ObjectBody,
458 ULONG HandleCount)
459 {
460 PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody;
461 KEVENT Event;
462 PIRP Irp;
463 PIO_STACK_LOCATION StackPtr;
464 NTSTATUS Status;
465 PDEVICE_OBJECT DeviceObject;
466
467 DPRINT("IopCloseFile()\n");
468
469 if (HandleCount > 1 || FileObject->DeviceObject == NULL) return;
470
471 /* Check if this is a direct open or not */
472 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
473 {
474 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
475 }
476 else
477 {
478 DeviceObject = IoGetRelatedDeviceObject(FileObject);
479 }
480
481 /* Clear and set up Events */
482 KeClearEvent(&FileObject->Event);
483 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
484
485 /* Allocate an IRP */
486 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
487
488 /* Set it up */
489 Irp->UserEvent = &Event;
490 Irp->UserIosb = &Irp->IoStatus;
491 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
492 Irp->Tail.Overlay.OriginalFileObject = FileObject;
493 Irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API;
494
495 /* Set up Stack Pointer Data */
496 StackPtr = IoGetNextIrpStackLocation(Irp);
497 StackPtr->MajorFunction = IRP_MJ_CLEANUP;
498 StackPtr->FileObject = FileObject;
499
500 /* Call the FS Driver */
501 Status = IoCallDriver(DeviceObject, Irp);
502
503 /* Wait for completion */
504 if (Status == STATUS_PENDING)
505 {
506 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
507 }
508 IoFreeIrp(Irp);
509 }
510
511 NTSTATUS
512 STDCALL
513 IopDeviceFsIoControl(IN HANDLE DeviceHandle,
514 IN HANDLE Event OPTIONAL,
515 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
516 IN PVOID UserApcContext OPTIONAL,
517 OUT PIO_STATUS_BLOCK IoStatusBlock,
518 IN ULONG IoControlCode,
519 IN PVOID InputBuffer,
520 IN ULONG InputBufferLength OPTIONAL,
521 OUT PVOID OutputBuffer,
522 IN ULONG OutputBufferLength OPTIONAL,
523 BOOLEAN IsDevIoCtl)
524 {
525 NTSTATUS Status = STATUS_SUCCESS;
526 PFILE_OBJECT FileObject;
527 PDEVICE_OBJECT DeviceObject;
528 PIRP Irp;
529 PIO_STACK_LOCATION StackPtr;
530 PKEVENT EventObject = NULL;
531 BOOLEAN LocalEvent = FALSE;
532 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
533
534 DPRINT("IopDeviceFsIoControl(DeviceHandle 0x%p Event 0x%p UserApcRoutine 0x%p "
535 "UserApcContext 0x%p IoStatusBlock 0x%p IoControlCode %x "
536 "InputBuffer 0x%p InputBufferLength %x OutputBuffer 0x%p "
537 "OutputBufferLength 0x%p)\n",
538 DeviceHandle,Event,UserApcRoutine,UserApcContext,IoStatusBlock,
539 IoControlCode,InputBuffer,InputBufferLength,OutputBuffer,
540 OutputBufferLength);
541
542 if (IoStatusBlock == NULL) return STATUS_ACCESS_VIOLATION;
543
544 /* Check granted access against the access rights from IoContolCode */
545 Status = ObReferenceObjectByHandle(DeviceHandle,
546 (IoControlCode >> 14) & 0x3,
547 IoFileObjectType,
548 PreviousMode,
549 (PVOID *) &FileObject,
550 NULL);
551 if (!NT_SUCCESS(Status)) return Status;
552
553 /* Check for an event */
554 if (Event)
555 {
556 /* Reference it */
557 Status = ObReferenceObjectByHandle(Event,
558 EVENT_MODIFY_STATE,
559 ExEventObjectType,
560 PreviousMode,
561 (PVOID*)&EventObject,
562 NULL);
563 if (!NT_SUCCESS(Status))
564 {
565 ObDereferenceObject (FileObject);
566 return Status;
567 }
568
569 /* Clear it */
570 KeClearEvent(EventObject);
571 }
572
573 /* Check if this is a direct open or not */
574 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
575 {
576 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
577 }
578 else
579 {
580 DeviceObject = IoGetRelatedDeviceObject(FileObject);
581 }
582
583 /* Check if we should use Sync IO or not */
584 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
585 {
586 /* Use File Object event */
587 KeClearEvent(&FileObject->Event);
588 }
589 else
590 {
591 /* Use local event */
592 LocalEvent = TRUE;
593 }
594
595 /* Build the IRP */
596 Irp = IoBuildDeviceIoControlRequest(IoControlCode,
597 DeviceObject,
598 InputBuffer,
599 InputBufferLength,
600 OutputBuffer,
601 OutputBufferLength,
602 FALSE,
603 EventObject,
604 IoStatusBlock);
605
606 /* Set some extra settings */
607 Irp->Tail.Overlay.OriginalFileObject = FileObject;
608 Irp->RequestorMode = PreviousMode;
609 Irp->Overlay.AsynchronousParameters.UserApcRoutine = UserApcRoutine;
610 Irp->Overlay.AsynchronousParameters.UserApcContext = UserApcContext;
611 StackPtr = IoGetNextIrpStackLocation(Irp);
612 StackPtr->FileObject = FileObject;
613 StackPtr->MajorFunction = IsDevIoCtl ?
614 IRP_MJ_DEVICE_CONTROL : IRP_MJ_FILE_SYSTEM_CONTROL;
615
616 /* Call the Driver */
617 Status = IoCallDriver(DeviceObject, Irp);
618 if (Status == STATUS_PENDING)
619 {
620 if (!LocalEvent)
621 {
622 KeWaitForSingleObject(&FileObject->Event,
623 Executive,
624 PreviousMode,
625 FileObject->Flags & FO_ALERTABLE_IO,
626 NULL);
627 Status = FileObject->FinalStatus;
628 }
629 }
630
631 /* Return the Status */
632 return Status;
633 }
634
635 /* FUNCTIONS *****************************************************************/
636
637 /*
638 * @unimplemented
639 */
640 NTSTATUS
641 STDCALL
642 IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass,
643 IN ULONG Length,
644 IN BOOLEAN SetOperation)
645 {
646 UNIMPLEMENTED;
647 return STATUS_NOT_IMPLEMENTED;
648 }
649
650 /*
651 * @unimplemented
652 */
653 NTSTATUS
654 STDCALL
655 IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer,
656 IN ULONG QuotaLength,
657 OUT PULONG ErrorOffset)
658 {
659 UNIMPLEMENTED;
660 return STATUS_NOT_IMPLEMENTED;
661 }
662
663 /*
664 * NAME EXPORTED
665 * IoCreateFile@56
666 *
667 * DESCRIPTION
668 * Either causes a new file or directory to be created, or it
669 * opens an existing file, device, directory or volume, giving
670 * the caller a handle for the file object. This handle can be
671 * used by subsequent calls to manipulate data within the file
672 * or the file object's state of attributes.
673 *
674 * ARGUMENTS
675 * FileHandle (OUT)
676 * Points to a variable which receives the file handle
677 * on return;
678 *
679 * DesiredAccess
680 * Desired access to the file;
681 *
682 * ObjectAttributes
683 * Structure describing the file;
684 *
685 * IoStatusBlock (OUT)
686 * Receives information about the operation on return;
687 *
688 * AllocationSize [OPTIONAL]
689 * Initial size of the file in bytes;
690 *
691 * FileAttributes
692 * Attributes to create the file with;
693 *
694 * ShareAccess
695 * Type of shared access the caller would like to the
696 * file;
697 *
698 * CreateDisposition
699 * Specifies what to do, depending on whether the
700 * file already exists;
701 *
702 * CreateOptions
703 * Options for creating a new file;
704 *
705 * EaBuffer [OPTIONAL]
706 * Undocumented;
707 *
708 * EaLength
709 * Undocumented;
710 *
711 * CreateFileType
712 * Type of file (normal, named pipe, mailslot) to create;
713 *
714 * ExtraCreateParameters [OPTIONAL]
715 * Additional creation data for named pipe and mailsots;
716 *
717 * Options
718 * Undocumented.
719 *
720 * RETURN VALUE
721 * Status
722 *
723 * NOTE
724 * Prototype taken from Bo Branten's ntifs.h v15.
725 * Description taken from old NtCreateFile's which is
726 * now a wrapper of this call.
727 *
728 * REVISIONS
729 *
730 * @implemented
731 */
732 NTSTATUS
733 STDCALL
734 IoCreateFile(OUT PHANDLE FileHandle,
735 IN ACCESS_MASK DesiredAccess,
736 IN POBJECT_ATTRIBUTES ObjectAttributes,
737 OUT PIO_STATUS_BLOCK IoStatusBlock,
738 IN PLARGE_INTEGER AllocationSize OPTIONAL,
739 IN ULONG FileAttributes,
740 IN ULONG ShareAccess,
741 IN ULONG CreateDisposition,
742 IN ULONG CreateOptions,
743 IN PVOID EaBuffer OPTIONAL,
744 IN ULONG EaLength,
745 IN CREATE_FILE_TYPE CreateFileType,
746 IN PVOID ExtraCreateParameters OPTIONAL,
747 IN ULONG Options)
748 {
749 PFILE_OBJECT FileObject = NULL;
750 PDEVICE_OBJECT DeviceObject;
751 PIRP Irp;
752 PIO_STACK_LOCATION StackLoc;
753 IO_SECURITY_CONTEXT SecurityContext;
754 KPROCESSOR_MODE AccessMode;
755 HANDLE LocalHandle;
756 IO_STATUS_BLOCK LocalIoStatusBlock;
757 LARGE_INTEGER SafeAllocationSize;
758 PVOID SystemEaBuffer = NULL;
759 NTSTATUS Status = STATUS_SUCCESS;
760
761 DPRINT("IoCreateFile(FileHandle 0x%p, DesiredAccess %x, "
762 "ObjectAttributes 0x%p ObjectAttributes->ObjectName->Buffer %S)\n",
763 FileHandle,DesiredAccess,ObjectAttributes,
764 ObjectAttributes->ObjectName->Buffer);
765
766 ASSERT_IRQL(PASSIVE_LEVEL);
767
768 if (IoStatusBlock == NULL || FileHandle == NULL)
769 return STATUS_ACCESS_VIOLATION;
770
771 LocalHandle = 0;
772
773 if(Options & IO_NO_PARAMETER_CHECKING)
774 AccessMode = KernelMode;
775 else
776 AccessMode = ExGetPreviousMode();
777
778 if(AccessMode != KernelMode)
779 {
780 _SEH_TRY
781 {
782 ProbeForWrite(FileHandle,
783 sizeof(HANDLE),
784 sizeof(ULONG));
785 ProbeForWrite(IoStatusBlock,
786 sizeof(IO_STATUS_BLOCK),
787 sizeof(ULONG));
788 if(AllocationSize != NULL)
789 {
790 ProbeForRead(AllocationSize,
791 sizeof(LARGE_INTEGER),
792 sizeof(ULONG));
793 SafeAllocationSize = *AllocationSize;
794 }
795 else
796 SafeAllocationSize.QuadPart = 0;
797
798 if(EaBuffer != NULL && EaLength > 0)
799 {
800 ProbeForRead(EaBuffer,
801 EaLength,
802 sizeof(ULONG));
803
804 /* marshal EaBuffer */
805 SystemEaBuffer = ExAllocatePool(NonPagedPool,
806 EaLength);
807 if(SystemEaBuffer == NULL)
808 {
809 Status = STATUS_INSUFFICIENT_RESOURCES;
810 _SEH_LEAVE;
811 }
812
813 RtlCopyMemory(SystemEaBuffer,
814 EaBuffer,
815 EaLength);
816 }
817 }
818 _SEH_HANDLE
819 {
820 Status = _SEH_GetExceptionCode();
821 }
822 _SEH_END;
823
824 if(!NT_SUCCESS(Status))
825 {
826 return Status;
827 }
828 }
829 else
830 {
831 if(AllocationSize != NULL)
832 SafeAllocationSize = *AllocationSize;
833 else
834 SafeAllocationSize.QuadPart = 0;
835
836 if(EaBuffer != NULL && EaLength > 0)
837 {
838 SystemEaBuffer = EaBuffer;
839 }
840 }
841
842 if(Options & IO_CHECK_CREATE_PARAMETERS)
843 {
844 DPRINT1("FIXME: IO_CHECK_CREATE_PARAMETERS not yet supported!\n");
845 }
846
847 Status = ObOpenObjectByName(ObjectAttributes,
848 NULL,
849 NULL,
850 AccessMode,
851 DesiredAccess,
852 NULL,
853 &LocalHandle);
854
855 if (NT_SUCCESS(Status))
856 {
857 Status = ObReferenceObjectByHandle(LocalHandle,
858 DesiredAccess,
859 NULL,
860 AccessMode,
861 (PVOID*)&DeviceObject,
862 NULL);
863 ZwClose(LocalHandle);
864 if (!NT_SUCCESS(Status))
865 {
866 return Status;
867 }
868 if (BODY_TO_HEADER(DeviceObject)->Type != IoDeviceObjectType)
869 {
870 ObDereferenceObject (DeviceObject);
871 return STATUS_OBJECT_NAME_COLLISION;
872 }
873 /* FIXME: wt... */
874 FileObject = IoCreateStreamFileObject(NULL, DeviceObject);
875 /* HACK */
876 FileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
877 DPRINT("%wZ\n", ObjectAttributes->ObjectName);
878
879 ObDereferenceObject (DeviceObject);
880 }
881
882
883 if (FileObject == NULL)
884 {
885 Status = ObCreateObject(AccessMode,
886 IoFileObjectType,
887 ObjectAttributes,
888 AccessMode,
889 NULL,
890 sizeof(FILE_OBJECT),
891 0,
892 0,
893 (PVOID*)&FileObject);
894 if (!NT_SUCCESS(Status))
895 {
896 DPRINT("ObCreateObject() failed! (Status %lx)\n", Status);
897 return Status;
898 }
899 }
900 RtlMapGenericMask(&DesiredAccess,
901 &BODY_TO_HEADER(FileObject)->Type->TypeInfo.GenericMapping);
902
903 Status = ObInsertObject ((PVOID)FileObject,
904 NULL,
905 DesiredAccess,
906 0,
907 NULL,
908 &LocalHandle);
909 if (!NT_SUCCESS(Status))
910 {
911 DPRINT("ObInsertObject() failed! (Status %lx)\n", Status);
912 ObDereferenceObject (FileObject);
913 return Status;
914 }
915
916 if (CreateOptions & FILE_SYNCHRONOUS_IO_ALERT)
917 {
918 FileObject->Flags |= (FO_ALERTABLE_IO | FO_SYNCHRONOUS_IO);
919 }
920 if (CreateOptions & FILE_SYNCHRONOUS_IO_NONALERT)
921 {
922 FileObject->Flags |= FO_SYNCHRONOUS_IO;
923 }
924
925 if (CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING)
926 FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
927
928 SecurityContext.SecurityQos = NULL; /* ?? */
929 SecurityContext.AccessState = NULL; /* ?? */
930 SecurityContext.DesiredAccess = DesiredAccess;
931 SecurityContext.FullCreateOptions = 0; /* ?? */
932
933 KeInitializeEvent(&FileObject->Lock, SynchronizationEvent, TRUE);
934 KeInitializeEvent(&FileObject->Event, NotificationEvent, FALSE);
935
936 DPRINT("FileObject 0x%p\n", FileObject);
937 DPRINT("FileObject->DeviceObject 0x%p\n", FileObject->DeviceObject);
938 /*
939 * Create a new IRP to hand to
940 * the FS driver: this may fail
941 * due to resource shortage.
942 */
943 Irp = IoAllocateIrp(FileObject->DeviceObject->StackSize, FALSE);
944 if (Irp == NULL)
945 {
946 ZwClose(LocalHandle);
947 return STATUS_UNSUCCESSFUL;
948 }
949
950 //trigger FileObject/Event dereferencing
951 Irp->Tail.Overlay.OriginalFileObject = FileObject;
952 Irp->RequestorMode = AccessMode;
953 Irp->UserIosb = &LocalIoStatusBlock;
954 Irp->AssociatedIrp.SystemBuffer = SystemEaBuffer;
955 Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
956 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
957 Irp->UserEvent = &FileObject->Event;
958 Irp->Overlay.AllocationSize = SafeAllocationSize;
959
960 /*
961 * Get the stack location for the new
962 * IRP and prepare it.
963 */
964 StackLoc = IoGetNextIrpStackLocation(Irp);
965 StackLoc->MinorFunction = 0;
966 StackLoc->Flags = (UCHAR)Options;
967 StackLoc->Control = 0;
968 StackLoc->DeviceObject = FileObject->DeviceObject;
969 StackLoc->FileObject = FileObject;
970
971 switch (CreateFileType)
972 {
973 default:
974 case CreateFileTypeNone:
975 StackLoc->MajorFunction = IRP_MJ_CREATE;
976 StackLoc->Parameters.Create.SecurityContext = &SecurityContext;
977 StackLoc->Parameters.Create.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
978 StackLoc->Parameters.Create.Options |= (CreateDisposition << 24);
979 StackLoc->Parameters.Create.FileAttributes = (USHORT)FileAttributes;
980 StackLoc->Parameters.Create.ShareAccess = (USHORT)ShareAccess;
981 StackLoc->Parameters.Create.EaLength = SystemEaBuffer != NULL ? EaLength : 0;
982 break;
983
984 case CreateFileTypeNamedPipe:
985 StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
986 StackLoc->Parameters.CreatePipe.SecurityContext = &SecurityContext;
987 StackLoc->Parameters.CreatePipe.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
988 StackLoc->Parameters.CreatePipe.Options |= (CreateDisposition << 24);
989 StackLoc->Parameters.CreatePipe.ShareAccess = (USHORT)ShareAccess;
990 StackLoc->Parameters.CreatePipe.Parameters = ExtraCreateParameters;
991 break;
992
993 case CreateFileTypeMailslot:
994 StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
995 StackLoc->Parameters.CreateMailslot.SecurityContext = &SecurityContext;
996 StackLoc->Parameters.CreateMailslot.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
997 StackLoc->Parameters.CreateMailslot.Options |= (CreateDisposition << 24);
998 StackLoc->Parameters.CreateMailslot.ShareAccess = (USHORT)ShareAccess;
999 StackLoc->Parameters.CreateMailslot.Parameters = ExtraCreateParameters;
1000 break;
1001 }
1002
1003 /*
1004 * Now call the driver and
1005 * possibly wait if it can
1006 * not complete the request
1007 * immediately.
1008 */
1009 Status = IofCallDriver(FileObject->DeviceObject, Irp );
1010 DPRINT("Status :%x\n", Status);
1011
1012 if (Status == STATUS_PENDING)
1013 {
1014 KeWaitForSingleObject(&FileObject->Event,
1015 Executive,
1016 AccessMode,
1017 FALSE,
1018 NULL);
1019 Status = LocalIoStatusBlock.Status;
1020 }
1021 if (!NT_SUCCESS(Status))
1022 {
1023 DPRINT("Failing create request with status %x\n", Status);
1024 FileObject->DeviceObject = NULL;
1025 FileObject->Vpb = NULL;
1026
1027 ZwClose(LocalHandle);
1028 }
1029 else
1030 {
1031 _SEH_TRY
1032 {
1033 *FileHandle = LocalHandle;
1034 *IoStatusBlock = LocalIoStatusBlock;
1035 }
1036 _SEH_HANDLE
1037 {
1038 Status = _SEH_GetExceptionCode();
1039 }
1040 _SEH_END;
1041 }
1042
1043 /* cleanup EABuffer if captured */
1044 if(AccessMode != KernelMode && SystemEaBuffer != NULL)
1045 {
1046 ExFreePool(SystemEaBuffer);
1047 }
1048
1049 ASSERT_IRQL(PASSIVE_LEVEL);
1050
1051 DPRINT("Finished IoCreateFile() (*FileHandle) 0x%p\n", (*FileHandle));
1052
1053 return Status;
1054 }
1055
1056 /*
1057 * @unimplemented
1058 */
1059 NTSTATUS
1060 STDCALL
1061 IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle,
1062 IN ACCESS_MASK DesiredAccess,
1063 IN POBJECT_ATTRIBUTES ObjectAttributes,
1064 OUT PIO_STATUS_BLOCK IoStatusBlock,
1065 IN PLARGE_INTEGER AllocationSize OPTIONAL,
1066 IN ULONG FileAttributes,
1067 IN ULONG ShareAccess,
1068 IN ULONG Disposition,
1069 IN ULONG CreateOptions,
1070 IN PVOID EaBuffer OPTIONAL,
1071 IN ULONG EaLength,
1072 IN CREATE_FILE_TYPE CreateFileType,
1073 IN PVOID ExtraCreateParameters OPTIONAL,
1074 IN ULONG Options,
1075 IN PVOID DeviceObject)
1076 {
1077 UNIMPLEMENTED;
1078 return STATUS_NOT_IMPLEMENTED;
1079 }
1080
1081 /*
1082 * NAME EXPORTED
1083 * IoCreateStreamFileObject@8
1084 *
1085 * DESCRIPTION
1086 *
1087 * ARGUMENTS
1088 * FileObject
1089 * ?
1090 *
1091 * DeviceObject
1092 * ?
1093 *
1094 * RETURN VALUE
1095 *
1096 * NOTE
1097 *
1098 * REVISIONS
1099 *
1100 * @implemented
1101 */
1102 PFILE_OBJECT
1103 STDCALL
1104 IoCreateStreamFileObject(PFILE_OBJECT FileObject,
1105 PDEVICE_OBJECT DeviceObject)
1106 {
1107 PFILE_OBJECT CreatedFileObject;
1108 NTSTATUS Status;
1109
1110 /* FIXME: This function should call ObInsertObject. The "Lite" version
1111 doesnt. This function is also called from IoCreateFile for some
1112 reason. These hacks need to be removed.
1113 */
1114
1115 DPRINT("IoCreateStreamFileObject(FileObject 0x%p, DeviceObject 0x%p)\n",
1116 FileObject, DeviceObject);
1117 PAGED_CODE();
1118
1119 /* Create the File Object */
1120 Status = ObCreateObject(KernelMode,
1121 IoFileObjectType,
1122 NULL,
1123 KernelMode,
1124 NULL,
1125 sizeof(FILE_OBJECT),
1126 0,
1127 0,
1128 (PVOID*)&CreatedFileObject);
1129 if (!NT_SUCCESS(Status))
1130 {
1131 DPRINT1("Could not create FileObject\n");
1132 return (NULL);
1133 }
1134
1135 /* Choose Device Object */
1136 if (FileObject) DeviceObject = FileObject->DeviceObject;
1137 DPRINT("DeviceObject 0x%p\n", DeviceObject);
1138
1139 /* HACK */
1140 DeviceObject = IoGetAttachedDevice(DeviceObject);
1141
1142 /* Set File Object Data */
1143 CreatedFileObject->DeviceObject = DeviceObject;
1144 CreatedFileObject->Vpb = DeviceObject->Vpb;
1145 CreatedFileObject->Type = IO_TYPE_FILE;
1146 CreatedFileObject->Flags |= FO_STREAM_FILE;
1147
1148 /* Initialize Lock and Event */
1149 KeInitializeEvent(&CreatedFileObject->Event, NotificationEvent, FALSE);
1150 KeInitializeEvent(&CreatedFileObject->Lock, SynchronizationEvent, TRUE);
1151
1152 /* Return file */
1153 return CreatedFileObject;
1154 }
1155
1156 /*
1157 * @unimplemented
1158 */
1159 PFILE_OBJECT
1160 STDCALL
1161 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL,
1162 IN PDEVICE_OBJECT DeviceObject OPTIONAL,
1163 OUT PHANDLE FileObjectHandle OPTIONAL)
1164 {
1165 UNIMPLEMENTED;
1166 return 0;
1167 }
1168
1169 /*
1170 * @unimplemented
1171 */
1172 PFILE_OBJECT
1173 STDCALL
1174 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL,
1175 IN PDEVICE_OBJECT DeviceObject OPTIONAL)
1176 {
1177 UNIMPLEMENTED;
1178 return 0;
1179 }
1180
1181 /*
1182 * @implemented
1183 */
1184 PGENERIC_MAPPING
1185 STDCALL
1186 IoGetFileObjectGenericMapping(VOID)
1187 {
1188 return &IopFileMapping;
1189 }
1190
1191 /*
1192 * @implemented
1193 */
1194 BOOLEAN
1195 STDCALL
1196 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject)
1197 {
1198 /* Return the flag status */
1199 return (FileObject->Flags & FO_REMOTE_ORIGIN);
1200 }
1201
1202 /*
1203 * @unimplemented
1204 */
1205 NTSTATUS
1206 STDCALL
1207 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject,
1208 OUT POBJECT_NAME_INFORMATION *ObjectNameInformation)
1209 {
1210 UNIMPLEMENTED;
1211 return STATUS_NOT_IMPLEMENTED;
1212 }
1213
1214 /*
1215 * @implemented
1216 */
1217 NTSTATUS
1218 STDCALL
1219 IoQueryFileInformation(IN PFILE_OBJECT FileObject,
1220 IN FILE_INFORMATION_CLASS FileInformationClass,
1221 IN ULONG Length,
1222 OUT PVOID FileInformation,
1223 OUT PULONG ReturnedLength)
1224 {
1225 IO_STATUS_BLOCK IoStatusBlock;
1226 PIRP Irp;
1227 PDEVICE_OBJECT DeviceObject;
1228 PIO_STACK_LOCATION StackPtr;
1229 BOOLEAN LocalEvent = FALSE;
1230 KEVENT Event;
1231 NTSTATUS Status;
1232
1233 ASSERT(FileInformation != NULL);
1234
1235 Status = ObReferenceObjectByPointer(FileObject,
1236 FILE_READ_ATTRIBUTES,
1237 IoFileObjectType,
1238 KernelMode);
1239 if (!NT_SUCCESS(Status)) return(Status);
1240
1241 DPRINT("FileObject 0x%p\n", FileObject);
1242
1243 /* Get the Device Object */
1244 DeviceObject = IoGetRelatedDeviceObject(FileObject);
1245
1246 /* Check if we should use Sync IO or not */
1247 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
1248 {
1249 /* Use File Object event */
1250 KeClearEvent(&FileObject->Event);
1251 }
1252 else
1253 {
1254 /* Use local event */
1255 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
1256 LocalEvent = TRUE;
1257 }
1258
1259 /* Allocate the IRP */
1260 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
1261
1262 /* Set the IRP */
1263 Irp->Tail.Overlay.OriginalFileObject = FileObject;
1264 Irp->RequestorMode = KernelMode;
1265 Irp->AssociatedIrp.SystemBuffer = FileInformation;
1266 Irp->UserIosb = &IoStatusBlock;
1267 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
1268 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
1269 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
1270
1271 /* Set the Stack Data */
1272 StackPtr = IoGetNextIrpStackLocation(Irp);
1273 StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
1274 StackPtr->FileObject = FileObject;
1275
1276 /* Set Parameters */
1277 StackPtr->Parameters.QueryFile.FileInformationClass = FileInformationClass;
1278 StackPtr->Parameters.QueryFile.Length = Length;
1279
1280 /* Call the Driver */
1281 Status = IoCallDriver(FileObject->DeviceObject, Irp);
1282
1283 if (Status == STATUS_PENDING)
1284 {
1285 if (LocalEvent)
1286 {
1287 KeWaitForSingleObject(&Event,
1288 Executive,
1289 KernelMode,
1290 FileObject->Flags & FO_ALERTABLE_IO,
1291 NULL);
1292 Status = IoStatusBlock.Status;
1293 }
1294 else
1295 {
1296 KeWaitForSingleObject(&FileObject->Event,
1297 Executive,
1298 KernelMode,
1299 FileObject->Flags & FO_ALERTABLE_IO,
1300 NULL);
1301 Status = FileObject->FinalStatus;
1302 }
1303 }
1304
1305
1306 /* Return the Length and Status. ReturnedLength is NOT optional */
1307 *ReturnedLength = IoStatusBlock.Information;
1308 return Status;
1309 }
1310
1311 /*
1312 * @unimplemented
1313 */
1314 NTSTATUS
1315 STDCALL
1316 IoSetFileOrigin(IN PFILE_OBJECT FileObject,
1317 IN BOOLEAN Remote)
1318 {
1319 UNIMPLEMENTED;
1320 return STATUS_NOT_IMPLEMENTED;
1321 }
1322
1323 /**
1324 * @name NtCancelIoFile
1325 *
1326 * Cancel all pending I/O operations in the current thread for specified
1327 * file object.
1328 *
1329 * @param FileHandle
1330 * Handle to file object to cancel requests for. No specific
1331 * access rights are needed.
1332 * @param IoStatusBlock
1333 * Pointer to status block which is filled with final completition
1334 * status on successful return.
1335 *
1336 * @return Status.
1337 *
1338 * @implemented
1339 */
1340 NTSTATUS
1341 STDCALL
1342 NtCancelIoFile(IN HANDLE FileHandle,
1343 OUT PIO_STATUS_BLOCK IoStatusBlock)
1344 {
1345 NTSTATUS Status;
1346 PFILE_OBJECT FileObject;
1347 PETHREAD Thread;
1348 PLIST_ENTRY IrpEntry;
1349 PIRP Irp;
1350 KIRQL OldIrql;
1351 BOOLEAN OurIrpsInList = FALSE;
1352 LARGE_INTEGER Interval;
1353
1354 if ((ULONG_PTR)IoStatusBlock >= (ULONG_PTR)MmUserProbeAddress &&
1355 KeGetPreviousMode() == UserMode)
1356 return STATUS_ACCESS_VIOLATION;
1357
1358 Status = ObReferenceObjectByHandle(FileHandle, 0, IoFileObjectType,
1359 KeGetPreviousMode(), (PVOID*)&FileObject,
1360 NULL);
1361 if (!NT_SUCCESS(Status))
1362 return Status;
1363
1364 /* IRP cancellations are synchronized at APC_LEVEL. */
1365 OldIrql = KfRaiseIrql(APC_LEVEL);
1366
1367 /*
1368 * Walk the list of active IRPs and cancel the ones that belong to
1369 * our file object.
1370 */
1371
1372 Thread = PsGetCurrentThread();
1373 for (IrpEntry = Thread->IrpList.Flink;
1374 IrpEntry != &Thread->IrpList;
1375 IrpEntry = IrpEntry->Flink)
1376 {
1377 Irp = CONTAINING_RECORD(IrpEntry, IRP, ThreadListEntry);
1378 if (Irp->Tail.Overlay.OriginalFileObject == FileObject)
1379 {
1380 IoCancelIrp(Irp);
1381 /* Don't break here, we want to cancel all IRPs for the file object. */
1382 OurIrpsInList = TRUE;
1383 }
1384 }
1385
1386 KfLowerIrql(OldIrql);
1387
1388 while (OurIrpsInList)
1389 {
1390 OurIrpsInList = FALSE;
1391
1392 /* Wait a short while and then look if all our IRPs were completed. */
1393 Interval.QuadPart = -1000000; /* 100 milliseconds */
1394 KeDelayExecutionThread(KernelMode, FALSE, &Interval);
1395
1396 OldIrql = KfRaiseIrql(APC_LEVEL);
1397
1398 /*
1399 * Look in the list if all IRPs for the specified file object
1400 * are completed (or cancelled). If someone sends a new IRP
1401 * for our file object while we're here we can happily loop
1402 * forever.
1403 */
1404
1405 for (IrpEntry = Thread->IrpList.Flink;
1406 IrpEntry != &Thread->IrpList;
1407 IrpEntry = IrpEntry->Flink)
1408 {
1409 Irp = CONTAINING_RECORD(IrpEntry, IRP, ThreadListEntry);
1410 if (Irp->Tail.Overlay.OriginalFileObject == FileObject)
1411 {
1412 OurIrpsInList = TRUE;
1413 break;
1414 }
1415 }
1416
1417 KfLowerIrql(OldIrql);
1418 }
1419
1420 _SEH_TRY
1421 {
1422 IoStatusBlock->Status = STATUS_SUCCESS;
1423 IoStatusBlock->Information = 0;
1424 Status = STATUS_SUCCESS;
1425 }
1426 _SEH_HANDLE
1427 {
1428 Status = STATUS_UNSUCCESSFUL;
1429 }
1430 _SEH_END;
1431
1432 ObDereferenceObject(FileObject);
1433
1434 return Status;
1435 }
1436
1437 /*
1438 * NAME EXPORTED
1439 * NtCreateFile@44
1440 *
1441 * DESCRIPTION
1442 * Entry point to call IoCreateFile with
1443 * default parameters.
1444 *
1445 * ARGUMENTS
1446 * See IoCreateFile.
1447 *
1448 * RETURN VALUE
1449 * See IoCreateFile.
1450 *
1451 * REVISIONS
1452 * 2000-03-25 (ea)
1453 * Code originally in NtCreateFile moved in IoCreateFile.
1454 *
1455 * @implemented
1456 */
1457 NTSTATUS
1458 STDCALL
1459 NtCreateFile(PHANDLE FileHandle,
1460 ACCESS_MASK DesiredAccess,
1461 POBJECT_ATTRIBUTES ObjectAttributes,
1462 PIO_STATUS_BLOCK IoStatusBlock,
1463 PLARGE_INTEGER AllocateSize,
1464 ULONG FileAttributes,
1465 ULONG ShareAccess,
1466 ULONG CreateDisposition,
1467 ULONG CreateOptions,
1468 PVOID EaBuffer,
1469 ULONG EaLength)
1470 {
1471 /* Call the I/O Function */
1472 return IoCreateFile(FileHandle,
1473 DesiredAccess,
1474 ObjectAttributes,
1475 IoStatusBlock,
1476 AllocateSize,
1477 FileAttributes,
1478 ShareAccess,
1479 CreateDisposition,
1480 CreateOptions,
1481 EaBuffer,
1482 EaLength,
1483 CreateFileTypeNone,
1484 NULL,
1485 0);
1486 }
1487
1488 NTSTATUS
1489 STDCALL
1490 NtCreateMailslotFile(OUT PHANDLE FileHandle,
1491 IN ACCESS_MASK DesiredAccess,
1492 IN POBJECT_ATTRIBUTES ObjectAttributes,
1493 OUT PIO_STATUS_BLOCK IoStatusBlock,
1494 IN ULONG CreateOptions,
1495 IN ULONG MailslotQuota,
1496 IN ULONG MaxMessageSize,
1497 IN PLARGE_INTEGER TimeOut)
1498 {
1499 MAILSLOT_CREATE_PARAMETERS Buffer;
1500
1501 DPRINT("NtCreateMailslotFile(FileHandle 0x%p, DesiredAccess %x, "
1502 "ObjectAttributes 0x%p ObjectAttributes->ObjectName->Buffer %S)\n",
1503 FileHandle,DesiredAccess,ObjectAttributes,
1504 ObjectAttributes->ObjectName->Buffer);
1505 PAGED_CODE();
1506
1507 /* Check for Timeout */
1508 if (TimeOut)
1509 {
1510 /* Enable it */
1511 Buffer.TimeoutSpecified = TRUE;
1512
1513 /* FIXME: Add SEH */
1514 Buffer.ReadTimeout = *TimeOut;
1515 }
1516 else
1517 {
1518 /* No timeout */
1519 Buffer.TimeoutSpecified = FALSE;
1520 }
1521
1522 /* Set Settings */
1523 Buffer.MailslotQuota = MailslotQuota;
1524 Buffer.MaximumMessageSize = MaxMessageSize;
1525
1526 /* Call I/O */
1527 return IoCreateFile(FileHandle,
1528 DesiredAccess,
1529 ObjectAttributes,
1530 IoStatusBlock,
1531 NULL,
1532 FILE_ATTRIBUTE_NORMAL,
1533 FILE_SHARE_READ | FILE_SHARE_WRITE,
1534 FILE_CREATE,
1535 CreateOptions,
1536 NULL,
1537 0,
1538 CreateFileTypeMailslot,
1539 (PVOID)&Buffer,
1540 0);
1541 }
1542
1543 NTSTATUS
1544 STDCALL
1545 NtCreateNamedPipeFile(PHANDLE FileHandle,
1546 ACCESS_MASK DesiredAccess,
1547 POBJECT_ATTRIBUTES ObjectAttributes,
1548 PIO_STATUS_BLOCK IoStatusBlock,
1549 ULONG ShareAccess,
1550 ULONG CreateDisposition,
1551 ULONG CreateOptions,
1552 ULONG NamedPipeType,
1553 ULONG ReadMode,
1554 ULONG CompletionMode,
1555 ULONG MaximumInstances,
1556 ULONG InboundQuota,
1557 ULONG OutboundQuota,
1558 PLARGE_INTEGER DefaultTimeout)
1559 {
1560 NAMED_PIPE_CREATE_PARAMETERS Buffer;
1561
1562 DPRINT("NtCreateNamedPipeFile(FileHandle 0x%p, DesiredAccess %x, "
1563 "ObjectAttributes 0x%p ObjectAttributes->ObjectName->Buffer %S)\n",
1564 FileHandle,DesiredAccess,ObjectAttributes,
1565 ObjectAttributes->ObjectName->Buffer);
1566 PAGED_CODE();
1567
1568 /* Check for Timeout */
1569 if (DefaultTimeout)
1570 {
1571 /* Enable it */
1572 Buffer.TimeoutSpecified = TRUE;
1573
1574 /* FIXME: Add SEH */
1575 Buffer.DefaultTimeout = *DefaultTimeout;
1576 }
1577 else
1578 {
1579 /* No timeout */
1580 Buffer.TimeoutSpecified = FALSE;
1581 }
1582
1583 /* Set Settings */
1584 Buffer.NamedPipeType = NamedPipeType;
1585 Buffer.ReadMode = ReadMode;
1586 Buffer.CompletionMode = CompletionMode;
1587 Buffer.MaximumInstances = MaximumInstances;
1588 Buffer.InboundQuota = InboundQuota;
1589 Buffer.OutboundQuota = OutboundQuota;
1590
1591 /* Call I/O */
1592 return IoCreateFile(FileHandle,
1593 DesiredAccess,
1594 ObjectAttributes,
1595 IoStatusBlock,
1596 NULL,
1597 FILE_ATTRIBUTE_NORMAL,
1598 ShareAccess,
1599 CreateDisposition,
1600 CreateOptions,
1601 NULL,
1602 0,
1603 CreateFileTypeNamedPipe,
1604 (PVOID)&Buffer,
1605 0);
1606 }
1607
1608 /*
1609 * NAME EXPORTED
1610 * NtDeleteFile@4
1611 *
1612 * DESCRIPTION
1613 *
1614 * ARGUMENTS
1615 * ObjectAttributes
1616 * ?
1617 *
1618 * RETURN VALUE
1619 *
1620 * REVISIONS
1621 *
1622 * @unimplemented
1623 */
1624 NTSTATUS
1625 STDCALL
1626 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes)
1627 {
1628 UNIMPLEMENTED;
1629 return(STATUS_NOT_IMPLEMENTED);
1630 }
1631
1632 /*
1633 * @implemented
1634 */
1635 NTSTATUS
1636 STDCALL
1637 NtDeviceIoControlFile(IN HANDLE DeviceHandle,
1638 IN HANDLE Event OPTIONAL,
1639 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
1640 IN PVOID UserApcContext OPTIONAL,
1641 OUT PIO_STATUS_BLOCK IoStatusBlock,
1642 IN ULONG IoControlCode,
1643 IN PVOID InputBuffer,
1644 IN ULONG InputBufferLength OPTIONAL,
1645 OUT PVOID OutputBuffer,
1646 IN ULONG OutputBufferLength OPTIONAL)
1647 {
1648 /* Call the Generic Function */
1649 return IopDeviceFsIoControl(DeviceHandle,
1650 Event,
1651 UserApcRoutine,
1652 UserApcContext,
1653 IoStatusBlock,
1654 IoControlCode,
1655 InputBuffer,
1656 InputBufferLength,
1657 OutputBuffer,
1658 OutputBufferLength,
1659 TRUE);
1660 }
1661
1662 /*
1663 * @implemented
1664 */
1665 NTSTATUS
1666 STDCALL
1667 NtFsControlFile(IN HANDLE DeviceHandle,
1668 IN HANDLE Event OPTIONAL,
1669 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
1670 IN PVOID UserApcContext OPTIONAL,
1671 OUT PIO_STATUS_BLOCK IoStatusBlock,
1672 IN ULONG IoControlCode,
1673 IN PVOID InputBuffer,
1674 IN ULONG InputBufferLength OPTIONAL,
1675 OUT PVOID OutputBuffer,
1676 IN ULONG OutputBufferLength OPTIONAL)
1677 {
1678 return IopDeviceFsIoControl(DeviceHandle,
1679 Event,
1680 UserApcRoutine,
1681 UserApcContext,
1682 IoStatusBlock,
1683 IoControlCode,
1684 InputBuffer,
1685 InputBufferLength,
1686 OutputBuffer,
1687 OutputBufferLength,
1688 FALSE);
1689 }
1690
1691 NTSTATUS
1692 STDCALL
1693 NtFlushWriteBuffer(VOID)
1694 {
1695 KeFlushWriteBuffer();
1696 return STATUS_SUCCESS;
1697 }
1698
1699 /*
1700 * FUNCTION: Flushes cached file data to disk
1701 * ARGUMENTS:
1702 * FileHandle = Points to the file
1703 * IoStatusBlock = Caller must supply storage to receive the result of
1704 * the flush buffers operation. The information field is
1705 * set to number of bytes flushed to disk.
1706 * RETURNS: Status
1707 * REMARKS: This function maps to the win32 FlushFileBuffers
1708 */
1709 NTSTATUS
1710 STDCALL
1711 NtFlushBuffersFile(IN HANDLE FileHandle,
1712 OUT PIO_STATUS_BLOCK IoStatusBlock)
1713 {
1714 PFILE_OBJECT FileObject = NULL;
1715 PIRP Irp;
1716 PIO_STACK_LOCATION StackPtr;
1717 NTSTATUS Status;
1718 PDEVICE_OBJECT DeviceObject;
1719 KEVENT Event;
1720 BOOLEAN LocalEvent = FALSE;
1721 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
1722
1723 /* Get the File Object */
1724 Status = ObReferenceObjectByHandle(FileHandle,
1725 FILE_WRITE_DATA,
1726 NULL,
1727 PreviousMode,
1728 (PVOID*)&FileObject,
1729 NULL);
1730 if (Status != STATUS_SUCCESS) return(Status);
1731
1732 /* Check if this is a direct open or not */
1733 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
1734 {
1735 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
1736 }
1737 else
1738 {
1739 DeviceObject = IoGetRelatedDeviceObject(FileObject);
1740 }
1741
1742 /* Check if we should use Sync IO or not */
1743 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
1744 {
1745 /* Use File Object event */
1746 KeClearEvent(&FileObject->Event);
1747 }
1748 else
1749 {
1750 /* Use local event */
1751 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
1752 LocalEvent = TRUE;
1753 }
1754
1755 /* Allocate the IRP */
1756 if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
1757 {
1758 ObDereferenceObject(FileObject);
1759 return STATUS_INSUFFICIENT_RESOURCES;
1760 }
1761
1762 /* Set up the IRP */
1763 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
1764 Irp->RequestorMode = PreviousMode;
1765 Irp->UserIosb = IoStatusBlock;
1766 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
1767 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
1768 Irp->Tail.Overlay.OriginalFileObject = FileObject;
1769
1770 /* Set up Stack Data */
1771 StackPtr = IoGetNextIrpStackLocation(Irp);
1772 StackPtr->MajorFunction = IRP_MJ_FLUSH_BUFFERS;
1773 StackPtr->FileObject = FileObject;
1774
1775 /* Call the Driver */
1776 Status = IoCallDriver(DeviceObject, Irp);
1777 if (Status == STATUS_PENDING)
1778 {
1779 if (LocalEvent)
1780 {
1781 KeWaitForSingleObject(&Event,
1782 Executive,
1783 PreviousMode,
1784 FileObject->Flags & FO_ALERTABLE_IO,
1785 NULL);
1786 Status = IoStatusBlock->Status;
1787 }
1788 else
1789 {
1790 KeWaitForSingleObject(&FileObject->Event,
1791 Executive,
1792 PreviousMode,
1793 FileObject->Flags & FO_ALERTABLE_IO,
1794 NULL);
1795 Status = FileObject->FinalStatus;
1796 }
1797 }
1798
1799 /* Return the Status */
1800 return Status;
1801 }
1802
1803 /*
1804 * @implemented
1805 */
1806 NTSTATUS
1807 STDCALL
1808 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle,
1809 IN HANDLE Event OPTIONAL,
1810 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
1811 IN PVOID ApcContext OPTIONAL,
1812 OUT PIO_STATUS_BLOCK IoStatusBlock,
1813 OUT PVOID Buffer,
1814 IN ULONG BufferSize,
1815 IN ULONG CompletionFilter,
1816 IN BOOLEAN WatchTree)
1817 {
1818 PIRP Irp;
1819 PDEVICE_OBJECT DeviceObject;
1820 PFILE_OBJECT FileObject;
1821 PIO_STACK_LOCATION IoStack;
1822 KPROCESSOR_MODE PreviousMode;
1823 NTSTATUS Status = STATUS_SUCCESS;
1824
1825 DPRINT("NtNotifyChangeDirectoryFile()\n");
1826
1827 PAGED_CODE();
1828
1829 PreviousMode = ExGetPreviousMode();
1830
1831 if(PreviousMode != KernelMode)
1832 {
1833 _SEH_TRY
1834 {
1835 ProbeForWrite(IoStatusBlock,
1836 sizeof(IO_STATUS_BLOCK),
1837 sizeof(ULONG));
1838 if(BufferSize != 0)
1839 {
1840 ProbeForWrite(Buffer,
1841 BufferSize,
1842 sizeof(ULONG));
1843 }
1844 }
1845 _SEH_HANDLE
1846 {
1847 Status = _SEH_GetExceptionCode();
1848 }
1849 _SEH_END;
1850
1851 if(!NT_SUCCESS(Status))
1852 {
1853 return Status;
1854 }
1855 }
1856
1857 Status = ObReferenceObjectByHandle(FileHandle,
1858 FILE_LIST_DIRECTORY,
1859 IoFileObjectType,
1860 PreviousMode,
1861 (PVOID *)&FileObject,
1862 NULL);
1863 if (Status != STATUS_SUCCESS) return(Status);
1864
1865
1866 DeviceObject = FileObject->DeviceObject;
1867
1868
1869 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
1870 if (Irp==NULL)
1871 {
1872 ObDereferenceObject(FileObject);
1873 return STATUS_UNSUCCESSFUL;
1874 }
1875
1876 if (Event == NULL)
1877 {
1878 Event = &FileObject->Event;
1879 }
1880
1881 /* Trigger FileObject/Event dereferencing */
1882 Irp->Tail.Overlay.OriginalFileObject = FileObject;
1883 Irp->RequestorMode = PreviousMode;
1884 Irp->UserIosb = IoStatusBlock;
1885 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
1886 Irp->UserEvent = Event;
1887 KeResetEvent( Event );
1888 Irp->UserBuffer = Buffer;
1889 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
1890 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
1891
1892 IoStack = IoGetNextIrpStackLocation(Irp);
1893
1894 IoStack->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
1895 IoStack->MinorFunction = IRP_MN_NOTIFY_CHANGE_DIRECTORY;
1896 IoStack->Flags = 0;
1897 IoStack->Control = 0;
1898 IoStack->DeviceObject = DeviceObject;
1899 IoStack->FileObject = FileObject;
1900
1901 if (WatchTree)
1902 {
1903 IoStack->Flags = SL_WATCH_TREE;
1904 }
1905
1906 IoStack->Parameters.NotifyDirectory.CompletionFilter = CompletionFilter;
1907 IoStack->Parameters.NotifyDirectory.Length = BufferSize;
1908
1909 Status = IoCallDriver(FileObject->DeviceObject,Irp);
1910
1911 /* FIXME: Should we wait here or not for synchronously opened files? */
1912
1913 return Status;
1914 }
1915
1916 /*
1917 * @unimplemented
1918 */
1919 NTSTATUS
1920 STDCALL
1921 NtLockFile(IN HANDLE FileHandle,
1922 IN HANDLE EventHandle OPTIONAL,
1923 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
1924 IN PVOID ApcContext OPTIONAL,
1925 OUT PIO_STATUS_BLOCK IoStatusBlock,
1926 IN PLARGE_INTEGER ByteOffset,
1927 IN PLARGE_INTEGER Length,
1928 IN PULONG Key,
1929 IN BOOLEAN FailImmediately,
1930 IN BOOLEAN ExclusiveLock)
1931 {
1932 PFILE_OBJECT FileObject = NULL;
1933 PLARGE_INTEGER LocalLength = NULL;
1934 PIRP Irp = NULL;
1935 PIO_STACK_LOCATION StackPtr;
1936 PDEVICE_OBJECT DeviceObject;
1937 PKEVENT Event = NULL;
1938 BOOLEAN LocalEvent = FALSE;
1939 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
1940 NTSTATUS Status = STATUS_SUCCESS;
1941 OBJECT_HANDLE_INFORMATION HandleInformation;
1942
1943 /* FIXME: instead of this, use SEH */
1944 if (!Length || !ByteOffset) return STATUS_INVALID_PARAMETER;
1945
1946 /* Get File Object */
1947 Status = ObReferenceObjectByHandle(FileHandle,
1948 0,
1949 IoFileObjectType,
1950 PreviousMode,
1951 (PVOID*)&FileObject,
1952 &HandleInformation);
1953 if (!NT_SUCCESS(Status)) return Status;
1954
1955 /* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
1956 if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_READ_DATA)))
1957 {
1958 DPRINT1("Invalid access rights\n");
1959 ObDereferenceObject(FileObject);
1960 return STATUS_ACCESS_DENIED;
1961 }
1962
1963 /* Get Event Object */
1964 if (EventHandle)
1965 {
1966 Status = ObReferenceObjectByHandle(EventHandle,
1967 EVENT_MODIFY_STATE,
1968 ExEventObjectType,
1969 PreviousMode,
1970 (PVOID *)&Event,
1971 NULL);
1972 if (Status != STATUS_SUCCESS) return(Status);
1973 KeClearEvent(Event);
1974 }
1975
1976 /* Check if this is a direct open or not */
1977 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
1978 {
1979 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
1980 }
1981 else
1982 {
1983 DeviceObject = IoGetRelatedDeviceObject(FileObject);
1984 }
1985
1986 /* Check if we should use Sync IO or not */
1987 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
1988 {
1989 /* Use File Object event */
1990 KeClearEvent(&FileObject->Event);
1991 }
1992 else
1993 {
1994 LocalEvent = TRUE;
1995 }
1996
1997 /* Allocate the IRP */
1998 if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
1999 {
2000 ObDereferenceObject(FileObject);
2001 return STATUS_INSUFFICIENT_RESOURCES;
2002 }
2003
2004 /* Allocate local buffer */
2005 LocalLength = ExAllocatePoolWithTag(NonPagedPool,
2006 sizeof(LARGE_INTEGER),
2007 TAG_LOCK);
2008 if (!LocalLength)
2009 {
2010 IoFreeIrp(Irp);
2011 ObDereferenceObject(FileObject);
2012 return STATUS_INSUFFICIENT_RESOURCES;
2013 }
2014 *LocalLength = *Length;
2015
2016 /* Set up the IRP */
2017 Irp->RequestorMode = PreviousMode;
2018 Irp->UserIosb = IoStatusBlock;
2019 Irp->UserEvent = Event;
2020 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2021 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2022
2023 /* Set up Stack Data */
2024 StackPtr = IoGetNextIrpStackLocation(Irp);
2025 StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
2026 StackPtr->MinorFunction = IRP_MN_LOCK;
2027 StackPtr->FileObject = FileObject;
2028
2029 /* Set Parameters */
2030 StackPtr->Parameters.LockControl.Length = LocalLength;
2031 StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset;
2032 StackPtr->Parameters.LockControl.Key = Key ? *Key : 0;
2033
2034 /* Set Flags */
2035 if (FailImmediately) StackPtr->Flags = SL_FAIL_IMMEDIATELY;
2036 if (ExclusiveLock) StackPtr->Flags |= SL_EXCLUSIVE_LOCK;
2037
2038 /* Call the Driver */
2039 FileObject->LockOperation = TRUE;
2040 Status = IoCallDriver(DeviceObject, Irp);
2041 if (Status == STATUS_PENDING)
2042 {
2043 if (!LocalEvent)
2044 {
2045 KeWaitForSingleObject(&FileObject->Event,
2046 Executive,
2047 PreviousMode,
2048 FileObject->Flags & FO_ALERTABLE_IO,
2049 NULL);
2050 Status = FileObject->FinalStatus;
2051 }
2052 }
2053
2054 /* Return the Status */
2055 return Status;
2056 }
2057
2058 /*
2059 * NAME EXPORTED
2060 * NtOpenFile@24
2061 *
2062 * DESCRIPTION
2063 * Opens an existing file (simpler than NtCreateFile).
2064 *
2065 * ARGUMENTS
2066 * FileHandle (OUT)
2067 * Variable that receives the file handle on return;
2068 *
2069 * DesiredAccess
2070 * Access desired by the caller to the file;
2071 *
2072 * ObjectAttributes
2073 * Structue describing the file to be opened;
2074 *
2075 * IoStatusBlock (OUT)
2076 * Receives details about the result of the
2077 * operation;
2078 *
2079 * ShareAccess
2080 * Type of shared access the caller requires;
2081 *
2082 * OpenOptions
2083 * Options for the file open.
2084 *
2085 * RETURN VALUE
2086 * Status.
2087 *
2088 * NOTE
2089 * Undocumented.
2090 *
2091 * @implemented
2092 */
2093 NTSTATUS
2094 STDCALL
2095 NtOpenFile(PHANDLE FileHandle,
2096 ACCESS_MASK DesiredAccess,
2097 POBJECT_ATTRIBUTES ObjectAttributes,
2098 PIO_STATUS_BLOCK IoStatusBlock,
2099 ULONG ShareAccess,
2100 ULONG OpenOptions)
2101 {
2102 /* Call the I/O Function */
2103 return IoCreateFile(FileHandle,
2104 DesiredAccess,
2105 ObjectAttributes,
2106 IoStatusBlock,
2107 NULL,
2108 0,
2109 ShareAccess,
2110 FILE_OPEN,
2111 OpenOptions,
2112 NULL,
2113 0,
2114 CreateFileTypeNone,
2115 NULL,
2116 0);
2117 }
2118
2119 NTSTATUS
2120 STDCALL
2121 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
2122 OUT PFILE_BASIC_INFORMATION FileInformation)
2123 {
2124 IO_STATUS_BLOCK IoStatusBlock;
2125 HANDLE FileHandle;
2126 NTSTATUS Status;
2127
2128 /* Open the file */
2129 Status = ZwOpenFile(&FileHandle,
2130 SYNCHRONIZE | FILE_READ_ATTRIBUTES,
2131 ObjectAttributes,
2132 &IoStatusBlock,
2133 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
2134 FILE_SYNCHRONOUS_IO_NONALERT);
2135 if (!NT_SUCCESS (Status))
2136 {
2137 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status);
2138 return Status;
2139 }
2140
2141 /* Get file attributes */
2142 Status = ZwQueryInformationFile(FileHandle,
2143 &IoStatusBlock,
2144 FileInformation,
2145 sizeof(FILE_BASIC_INFORMATION),
2146 FileBasicInformation);
2147 if (!NT_SUCCESS (Status))
2148 {
2149 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status);
2150 }
2151
2152 ZwClose(FileHandle);
2153 return Status;
2154 }
2155
2156 /*
2157 * @implemented
2158 *
2159 * FUNCTION: Queries a directory file.
2160 * ARGUMENTS:
2161 * FileHandle = Handle to a directory file
2162 * EventHandle = Handle to the event signaled on completion
2163 * ApcRoutine = Asynchroneous procedure callback, called on completion
2164 * ApcContext = Argument to the apc.
2165 * IoStatusBlock = Caller supplies storage for extended status information.
2166 * FileInformation = Caller supplies storage for the resulting information.
2167 *
2168 * FileNameInformation FILE_NAMES_INFORMATION
2169 * FileDirectoryInformation FILE_DIRECTORY_INFORMATION
2170 * FileFullDirectoryInformation FILE_FULL_DIRECTORY_INFORMATION
2171 * FileBothDirectoryInformation FILE_BOTH_DIR_INFORMATION
2172 *
2173 * Length = Size of the storage supplied
2174 * FileInformationClass = Indicates the type of information requested.
2175 * ReturnSingleEntry = Specify true if caller only requests the first
2176 * directory found.
2177 * FileName = Initial directory name to query, that may contain wild
2178 * cards.
2179 * RestartScan = Number of times the action should be repeated
2180 * RETURNS: Status [ STATUS_SUCCESS, STATUS_ACCESS_DENIED, STATUS_INSUFFICIENT_RESOURCES,
2181 * STATUS_INVALID_PARAMETER, STATUS_INVALID_DEVICE_REQUEST, STATUS_BUFFER_OVERFLOW,
2182 * STATUS_INVALID_INFO_CLASS, STATUS_NO_SUCH_FILE, STATUS_NO_MORE_FILES ]
2183 */
2184 NTSTATUS
2185 STDCALL
2186 NtQueryDirectoryFile(IN HANDLE FileHandle,
2187 IN HANDLE PEvent OPTIONAL,
2188 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
2189 IN PVOID ApcContext OPTIONAL,
2190 OUT PIO_STATUS_BLOCK IoStatusBlock,
2191 OUT PVOID FileInformation,
2192 IN ULONG Length,
2193 IN FILE_INFORMATION_CLASS FileInformationClass,
2194 IN BOOLEAN ReturnSingleEntry,
2195 IN PUNICODE_STRING FileName OPTIONAL,
2196 IN BOOLEAN RestartScan)
2197 {
2198 PIRP Irp;
2199 PDEVICE_OBJECT DeviceObject;
2200 PFILE_OBJECT FileObject;
2201 PIO_STACK_LOCATION StackPtr;
2202 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
2203 NTSTATUS Status = STATUS_SUCCESS;
2204 BOOLEAN LocalEvent = FALSE;
2205 PKEVENT Event = NULL;
2206
2207 DPRINT("NtQueryDirectoryFile()\n");
2208 PAGED_CODE();
2209
2210 /* Validate User-Mode Buffers */
2211 if(PreviousMode != KernelMode)
2212 {
2213 _SEH_TRY
2214 {
2215 ProbeForWrite(IoStatusBlock,
2216 sizeof(IO_STATUS_BLOCK),
2217 sizeof(ULONG));
2218 ProbeForWrite(FileInformation,
2219 Length,
2220 sizeof(ULONG));
2221 }
2222 _SEH_HANDLE
2223 {
2224 Status = _SEH_GetExceptionCode();
2225 }
2226 _SEH_END;
2227
2228 if(!NT_SUCCESS(Status)) return Status;
2229 }
2230
2231 /* Get File Object */
2232 Status = ObReferenceObjectByHandle(FileHandle,
2233 FILE_LIST_DIRECTORY,
2234 IoFileObjectType,
2235 PreviousMode,
2236 (PVOID *)&FileObject,
2237 NULL);
2238 if (Status != STATUS_SUCCESS) return(Status);
2239
2240 /* Get Event Object */
2241 if (PEvent)
2242 {
2243 Status = ObReferenceObjectByHandle(PEvent,
2244 EVENT_MODIFY_STATE,
2245 ExEventObjectType,
2246 PreviousMode,
2247 (PVOID *)&Event,
2248 NULL);
2249 if (Status != STATUS_SUCCESS) return(Status);
2250 KeClearEvent(Event);
2251 }
2252
2253 /* Check if this is a direct open or not */
2254 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
2255 {
2256 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
2257 }
2258 else
2259 {
2260 DeviceObject = IoGetRelatedDeviceObject(FileObject);
2261 }
2262
2263 /* Check if we should use Sync IO or not */
2264 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
2265 {
2266 /* Use File Object event */
2267 KeClearEvent(&FileObject->Event);
2268 }
2269 else
2270 {
2271 LocalEvent = TRUE;
2272 }
2273
2274 /* Allocate the IRP */
2275 if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
2276 {
2277 ObDereferenceObject(FileObject);
2278 return STATUS_INSUFFICIENT_RESOURCES;
2279 }
2280
2281 /* Set up the IRP */
2282 Irp->RequestorMode = PreviousMode;
2283 Irp->UserIosb = IoStatusBlock;
2284 Irp->UserEvent = Event;
2285 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2286 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2287 Irp->UserBuffer = FileInformation;
2288 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
2289 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
2290
2291 /* Set up Stack Data */
2292 StackPtr = IoGetNextIrpStackLocation(Irp);
2293 StackPtr->FileObject = FileObject;
2294 StackPtr->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
2295 StackPtr->MinorFunction = IRP_MN_QUERY_DIRECTORY;
2296
2297 /* Set Parameters */
2298 StackPtr->Parameters.QueryDirectory.FileInformationClass = FileInformationClass;
2299 StackPtr->Parameters.QueryDirectory.FileName = FileName;
2300 StackPtr->Parameters.QueryDirectory.FileIndex = 0;
2301 StackPtr->Parameters.QueryDirectory.Length = Length;
2302 StackPtr->Flags = 0;
2303 if (RestartScan) StackPtr->Flags = SL_RESTART_SCAN;
2304 if (ReturnSingleEntry) StackPtr->Flags |= SL_RETURN_SINGLE_ENTRY;
2305
2306 /* Call the Driver */
2307 Status = IoCallDriver(DeviceObject, Irp);
2308 if (Status == STATUS_PENDING)
2309 {
2310 if (!LocalEvent)
2311 {
2312 KeWaitForSingleObject(&FileObject->Event,
2313 Executive,
2314 PreviousMode,
2315 FileObject->Flags & FO_ALERTABLE_IO,
2316 NULL);
2317 Status = FileObject->FinalStatus;
2318 }
2319 }
2320
2321 /* Return the Status */
2322 return Status;
2323 }
2324
2325 /*
2326 * @unimplemented
2327 */
2328 NTSTATUS STDCALL
2329 NtQueryEaFile(IN HANDLE FileHandle,
2330 OUT PIO_STATUS_BLOCK IoStatusBlock,
2331 OUT PVOID Buffer,
2332 IN ULONG Length,
2333 IN BOOLEAN ReturnSingleEntry,
2334 IN PVOID EaList OPTIONAL,
2335 IN ULONG EaListLength,
2336 IN PULONG EaIndex OPTIONAL,
2337 IN BOOLEAN RestartScan)
2338 {
2339 UNIMPLEMENTED;
2340 return STATUS_NOT_IMPLEMENTED;
2341 }
2342
2343 NTSTATUS
2344 STDCALL
2345 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
2346 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation)
2347 {
2348 IO_STATUS_BLOCK IoStatusBlock;
2349 HANDLE FileHandle;
2350 NTSTATUS Status;
2351
2352 /* Open the file */
2353 Status = ZwOpenFile(&FileHandle,
2354 SYNCHRONIZE | FILE_READ_ATTRIBUTES,
2355 ObjectAttributes,
2356 &IoStatusBlock,
2357 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
2358 FILE_SYNCHRONOUS_IO_NONALERT);
2359 if (!NT_SUCCESS (Status))
2360 {
2361 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status);
2362 return Status;
2363 }
2364
2365 /* Get file attributes */
2366 Status = ZwQueryInformationFile(FileHandle,
2367 &IoStatusBlock,
2368 FileInformation,
2369 sizeof(FILE_NETWORK_OPEN_INFORMATION),
2370 FileNetworkOpenInformation);
2371 if (!NT_SUCCESS (Status))
2372 {
2373 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status);
2374 }
2375
2376 ZwClose (FileHandle);
2377 return Status;
2378 }
2379
2380 /*
2381 * @implemented
2382 */
2383 NTSTATUS STDCALL
2384 NtQueryInformationFile(HANDLE FileHandle,
2385 PIO_STATUS_BLOCK IoStatusBlock,
2386 PVOID FileInformation,
2387 ULONG Length,
2388 FILE_INFORMATION_CLASS FileInformationClass)
2389 {
2390 OBJECT_HANDLE_INFORMATION HandleInformation;
2391 PFILE_OBJECT FileObject;
2392 NTSTATUS Status;
2393 PIRP Irp;
2394 PDEVICE_OBJECT DeviceObject;
2395 PIO_STACK_LOCATION StackPtr;
2396 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
2397 KEVENT Event;
2398 BOOLEAN LocalEvent = FALSE;
2399 BOOLEAN Failed = FALSE;
2400
2401 ASSERT(IoStatusBlock != NULL);
2402 ASSERT(FileInformation != NULL);
2403
2404 DPRINT("NtQueryInformationFile(Handle 0x%p StatBlk 0x%p FileInfo 0x%p Length %d "
2405 "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
2406 Length, FileInformationClass);
2407
2408 /* Reference the Handle */
2409 Status = ObReferenceObjectByHandle(FileHandle,
2410 0,
2411 IoFileObjectType,
2412 PreviousMode,
2413 (PVOID *)&FileObject,
2414 &HandleInformation);
2415 if (!NT_SUCCESS(Status)) return Status;
2416
2417 /* Check information class specific access rights */
2418 switch (FileInformationClass)
2419 {
2420 case FileBasicInformation:
2421 if (!(HandleInformation.GrantedAccess & FILE_READ_ATTRIBUTES))
2422 Failed = TRUE;
2423 break;
2424
2425 case FilePositionInformation:
2426 if (!(HandleInformation.GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA)) ||
2427 !(FileObject->Flags & FO_SYNCHRONOUS_IO))
2428 Failed = TRUE;
2429 break;
2430
2431 case FileAlignmentInformation:
2432 if (!(FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING))
2433 Failed = TRUE;
2434 break;
2435
2436 default:
2437 break;
2438 }
2439
2440 if (Failed)
2441 {
2442 DPRINT1("NtQueryInformationFile() returns STATUS_ACCESS_DENIED!\n");
2443 ObDereferenceObject(FileObject);
2444 return STATUS_ACCESS_DENIED;
2445 }
2446
2447 DPRINT("FileObject 0x%p\n", FileObject);
2448
2449 /* Check if this is a direct open or not */
2450 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
2451 {
2452 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
2453 }
2454 else
2455 {
2456 DeviceObject = IoGetRelatedDeviceObject(FileObject);
2457 }
2458
2459 /* Check if we should use Sync IO or not */
2460 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
2461 {
2462 /* Use File Object event */
2463 KeClearEvent(&FileObject->Event);
2464 }
2465 else
2466 {
2467 /* Use local event */
2468 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
2469 LocalEvent = TRUE;
2470 }
2471
2472 /* Allocate the IRP */
2473 if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
2474 {
2475 ObDereferenceObject(FileObject);
2476 return STATUS_INSUFFICIENT_RESOURCES;
2477 }
2478
2479 /* Allocate the System Buffer */
2480 if (!(Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
2481 Length,
2482 TAG_SYSB)))
2483 {
2484 IoFreeIrp(Irp);
2485 ObDereferenceObject(FileObject);
2486 return STATUS_INSUFFICIENT_RESOURCES;
2487 }
2488
2489 /* Set up the IRP */
2490 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2491 Irp->RequestorMode = PreviousMode;
2492 Irp->UserIosb = IoStatusBlock;
2493 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
2494 Irp->UserBuffer = FileInformation;
2495 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2496 Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER | IRP_INPUT_OPERATION;
2497 Irp->Flags |= (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
2498
2499 /* Set up Stack Data */
2500 StackPtr = IoGetNextIrpStackLocation(Irp);
2501 StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
2502 StackPtr->FileObject = FileObject;
2503
2504 /* Set the Parameters */
2505 StackPtr->Parameters.QueryFile.FileInformationClass = FileInformationClass;
2506 StackPtr->Parameters.QueryFile.Length = Length;
2507
2508 /* Call the Driver */
2509 Status = IoCallDriver(DeviceObject, Irp);
2510 if (Status == STATUS_PENDING)
2511 {
2512 if (LocalEvent)
2513 {
2514 KeWaitForSingleObject(&Event,
2515 Executive,
2516 PreviousMode,
2517 FileObject->Flags & FO_ALERTABLE_IO,
2518 NULL);
2519 Status = IoStatusBlock->Status;
2520 }
2521 else
2522 {
2523 KeWaitForSingleObject(&FileObject->Event,
2524 Executive,
2525 PreviousMode,
2526 FileObject->Flags & FO_ALERTABLE_IO,
2527 NULL);
2528 Status = FileObject->FinalStatus;
2529 }
2530 }
2531
2532 /* Return the Status */
2533 return Status;
2534 }
2535
2536 /*
2537 * @unimplemented
2538 */
2539 NTSTATUS
2540 STDCALL
2541 NtQueryQuotaInformationFile(IN HANDLE FileHandle,
2542 OUT PIO_STATUS_BLOCK IoStatusBlock,
2543 OUT PVOID Buffer,
2544 IN ULONG Length,
2545 IN BOOLEAN ReturnSingleEntry,
2546 IN PVOID SidList OPTIONAL,
2547 IN ULONG SidListLength,
2548 IN PSID StartSid OPTIONAL,
2549 IN BOOLEAN RestartScan)
2550 {
2551 UNIMPLEMENTED;
2552 return STATUS_NOT_IMPLEMENTED;
2553 }
2554
2555 /*
2556 * NAME EXPORTED
2557 * NtReadFile
2558 *
2559 * DESCRIPTION
2560 *
2561 * ARGUMENTS
2562 *
2563 * RETURN VALUE
2564 *
2565 * REVISIONS
2566 *
2567 * @implemented
2568 */
2569 NTSTATUS
2570 STDCALL
2571 NtReadFile(IN HANDLE FileHandle,
2572 IN HANDLE Event OPTIONAL,
2573 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
2574 IN PVOID ApcContext OPTIONAL,
2575 OUT PIO_STATUS_BLOCK IoStatusBlock,
2576 OUT PVOID Buffer,
2577 IN ULONG Length,
2578 IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for asynch. operations! */
2579 IN PULONG Key OPTIONAL)
2580 {
2581 NTSTATUS Status = STATUS_SUCCESS;
2582 PFILE_OBJECT FileObject;
2583 PIRP Irp = NULL;
2584 PDEVICE_OBJECT DeviceObject;
2585 PIO_STACK_LOCATION StackPtr;
2586 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
2587 BOOLEAN LocalEvent = FALSE;
2588 PKEVENT EventObject = NULL;
2589
2590 DPRINT("NtReadFile(FileHandle 0x%p Buffer 0x%p Length %x ByteOffset 0x%p, "
2591 "IoStatusBlock 0x%p)\n", FileHandle, Buffer, Length, ByteOffset,
2592 IoStatusBlock);
2593 PAGED_CODE();
2594
2595 /* Validate User-Mode Buffers */
2596 if(PreviousMode != KernelMode)
2597 {
2598 _SEH_TRY
2599 {
2600 ProbeForWrite(IoStatusBlock,
2601 sizeof(IO_STATUS_BLOCK),
2602 sizeof(ULONG));
2603 #if 0
2604 ProbeForWrite(Buffer,
2605 Length,
2606 sizeof(ULONG));
2607 #endif
2608 }
2609 _SEH_HANDLE
2610 {
2611 Status = _SEH_GetExceptionCode();
2612 }
2613 _SEH_END;
2614
2615 if(!NT_SUCCESS(Status)) return Status;
2616 }
2617
2618 /* Get File Object */
2619 Status = ObReferenceObjectByHandle(FileHandle,
2620 FILE_READ_DATA,
2621 IoFileObjectType,
2622 PreviousMode,
2623 (PVOID*)&FileObject,
2624 NULL);
2625 if (!NT_SUCCESS(Status)) return Status;
2626
2627 /* Check the Byte Offset */
2628 if (!ByteOffset ||
2629 (ByteOffset->u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
2630 ByteOffset->u.HighPart == -1))
2631 {
2632 /* a valid ByteOffset is required if asynch. op. */
2633 if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
2634 {
2635 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
2636 ObDereferenceObject(FileObject);
2637 return STATUS_INVALID_PARAMETER;
2638 }
2639
2640 /* Use the Current Byte OFfset */
2641 ByteOffset = &FileObject->CurrentByteOffset;
2642 }
2643
2644 /* Check for event */
2645 if (Event)
2646 {
2647 /* Reference it */
2648 Status = ObReferenceObjectByHandle(Event,
2649 EVENT_MODIFY_STATE,
2650 ExEventObjectType,
2651 PreviousMode,
2652 (PVOID*)&EventObject,
2653 NULL);
2654 if (!NT_SUCCESS(Status))
2655 {
2656 ObDereferenceObject(FileObject);
2657 return Status;
2658 }
2659 KeClearEvent(EventObject);
2660 }
2661
2662 /* Check if this is a direct open or not */
2663 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
2664 {
2665 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
2666 }
2667 else
2668 {
2669 DeviceObject = IoGetRelatedDeviceObject(FileObject);
2670 }
2671
2672 /* Check if we should use Sync IO or not */
2673 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
2674 {
2675 /* Use File Object event */
2676 KeClearEvent(&FileObject->Event);
2677 }
2678 else
2679 {
2680 LocalEvent = TRUE;
2681 }
2682
2683 /* Create the IRP */
2684 _SEH_TRY
2685 {
2686 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
2687 DeviceObject,
2688 Buffer,
2689 Length,
2690 ByteOffset,
2691 EventObject,
2692 IoStatusBlock);
2693 if (Irp == NULL)
2694 {
2695 Status = STATUS_INSUFFICIENT_RESOURCES;
2696 }
2697 }
2698 _SEH_HANDLE
2699 {
2700 Status = _SEH_GetExceptionCode();
2701 }
2702 _SEH_END;
2703
2704 /* Cleanup if IRP Allocation Failed */
2705 if (!NT_SUCCESS(Status))
2706 {
2707 if (Event) ObDereferenceObject(EventObject);
2708 ObDereferenceObject(FileObject);
2709 return Status;
2710 }
2711
2712 /* Set up IRP Data */
2713 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2714 Irp->RequestorMode = PreviousMode;
2715 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
2716 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
2717 Irp->Flags |= IRP_READ_OPERATION;
2718 #if 0
2719 /* FIXME:
2720 * Vfat doesn't handle non cached files correctly.
2721 */
2722 if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) Irp->Flags |= IRP_NOCACHE;
2723 #endif
2724
2725 /* Setup Stack Data */
2726 StackPtr = IoGetNextIrpStackLocation(Irp);
2727 StackPtr->FileObject = FileObject;
2728 StackPtr->Parameters.Read.Key = Key ? *Key : 0;
2729
2730 /* Call the Driver */
2731 Status = IoCallDriver(DeviceObject, Irp);
2732 if (Status == STATUS_PENDING)
2733 {
2734 if (!LocalEvent)
2735 {
2736 KeWaitForSingleObject(&FileObject->Event,
2737 Executive,
2738 PreviousMode,
2739 FileObject->Flags & FO_ALERTABLE_IO,
2740 NULL);
2741 Status = FileObject->FinalStatus;
2742 }
2743 }
2744
2745 /* Return the Status */
2746 return Status;
2747 }
2748
2749 /*
2750 * NAME EXPORTED
2751 * NtReadFileScatter
2752 *
2753 * DESCRIPTION
2754 *
2755 * ARGUMENTS
2756 *
2757 * RETURN VALUE
2758 *
2759 * REVISIONS
2760 */
2761 NTSTATUS
2762 STDCALL
2763 NtReadFileScatter(IN HANDLE FileHandle,
2764 IN HANDLE Event OPTIONAL,
2765 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
2766 IN PVOID UserApcContext OPTIONAL,
2767 OUT PIO_STATUS_BLOCK UserIoStatusBlock,
2768 IN FILE_SEGMENT_ELEMENT BufferDescription [],
2769 IN ULONG BufferLength,
2770 IN PLARGE_INTEGER ByteOffset,
2771 IN PULONG Key OPTIONAL)
2772 {
2773 UNIMPLEMENTED;
2774 return(STATUS_NOT_IMPLEMENTED);
2775 }
2776
2777 /*
2778 * @unimplemented
2779 */
2780 NTSTATUS
2781 STDCALL
2782 NtSetEaFile(IN HANDLE FileHandle,
2783 IN PIO_STATUS_BLOCK IoStatusBlock,
2784 IN PVOID EaBuffer,
2785 IN ULONG EaBufferSize)
2786 {
2787 UNIMPLEMENTED;
2788 return STATUS_NOT_IMPLEMENTED;
2789 }
2790
2791 /*
2792 * @implemented
2793 */
2794 NTSTATUS STDCALL
2795 NtSetInformationFile(HANDLE FileHandle,
2796 PIO_STATUS_BLOCK IoStatusBlock,
2797 PVOID FileInformation,
2798 ULONG Length,
2799 FILE_INFORMATION_CLASS FileInformationClass)
2800 {
2801 OBJECT_HANDLE_INFORMATION HandleInformation;
2802 PIO_STACK_LOCATION StackPtr;
2803 PFILE_OBJECT FileObject;
2804 PDEVICE_OBJECT DeviceObject;
2805 PIRP Irp;
2806 KEVENT Event;
2807 BOOLEAN LocalEvent = FALSE;
2808 NTSTATUS Status = STATUS_SUCCESS;
2809 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
2810 BOOLEAN Failed = FALSE;
2811
2812 ASSERT(IoStatusBlock != NULL);
2813 ASSERT(FileInformation != NULL);
2814
2815 DPRINT("NtSetInformationFile(Handle 0x%p StatBlk 0x%p FileInfo 0x%p Length %d "
2816 "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
2817 Length, FileInformationClass);
2818
2819 /* Get the file object from the file handle */
2820 Status = ObReferenceObjectByHandle(FileHandle,
2821 0,
2822 IoFileObjectType,
2823 PreviousMode,
2824 (PVOID *)&FileObject,
2825 &HandleInformation);
2826 if (!NT_SUCCESS(Status)) return Status;
2827
2828 /* Check information class specific access rights */
2829 switch (FileInformationClass)
2830 {
2831 case FileBasicInformation:
2832 if (!(HandleInformation.GrantedAccess & FILE_WRITE_ATTRIBUTES))
2833 Failed = TRUE;
2834 break;
2835
2836 case FileDispositionInformation:
2837 if (!(HandleInformation.GrantedAccess & DELETE))
2838 Failed = TRUE;
2839 break;
2840
2841 case FilePositionInformation:
2842 if (!(HandleInformation.GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA)) ||
2843 !(FileObject->Flags & FO_SYNCHRONOUS_IO))
2844 Failed = TRUE;
2845 break;
2846
2847 case FileEndOfFileInformation:
2848 if (!(HandleInformation.GrantedAccess & FILE_WRITE_DATA))
2849 Failed = TRUE;
2850 break;
2851
2852 default:
2853 break;
2854 }
2855
2856 if (Failed)
2857 {
2858 DPRINT1("NtSetInformationFile() returns STATUS_ACCESS_DENIED!\n");
2859 ObDereferenceObject(FileObject);
2860 return STATUS_ACCESS_DENIED;
2861 }
2862
2863 DPRINT("FileObject 0x%p\n", FileObject);
2864
2865 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
2866 /* Handle IO Completion Port quickly */
2867 if (FileInformationClass == FileCompletionInformation)
2868 {
2869 PVOID Queue;
2870 PFILE_COMPLETION_INFORMATION CompletionInfo = FileInformation;
2871 PIO_COMPLETION_CONTEXT Context;
2872
2873 if (Length < sizeof(FILE_COMPLETION_INFORMATION))
2874 {
2875 Status = STATUS_INFO_LENGTH_MISMATCH;
2876 }
2877 else
2878 {
2879 /* Reference the Port */
2880 Status = ObReferenceObjectByHandle(CompletionInfo->Port,
2881 IO_COMPLETION_MODIFY_STATE,
2882 IoCompletionType,
2883 PreviousMode,
2884 (PVOID*)&Queue,
2885 NULL);
2886 if (NT_SUCCESS(Status))
2887 {
2888 /* Allocate the Context */
2889 Context = ExAllocatePoolWithTag(PagedPool,
2890 sizeof(IO_COMPLETION_CONTEXT),
2891 TAG('I', 'o', 'C', 'p'));
2892
2893 /* Set the Data */
2894 Context->Key = CompletionInfo->Key;
2895 Context->Port = Queue;
2896 FileObject->CompletionContext = Context;
2897
2898 /* Dereference the Port now */
2899 ObDereferenceObject(Queue);
2900 }
2901 }
2902
2903 /* Complete the I/O */
2904 ObDereferenceObject(FileObject);
2905 return Status;
2906 }
2907
2908 /* Check if this is a direct open or not */
2909 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
2910 {
2911 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
2912 }
2913 else
2914 {
2915 DeviceObject = IoGetRelatedDeviceObject(FileObject);
2916 }
2917
2918 /* Check if we should use Sync IO or not */
2919 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
2920 {
2921 /* Use File Object event */
2922 KeClearEvent(&FileObject->Event);
2923 }
2924 else
2925 {
2926 /* Use local event */
2927 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
2928 LocalEvent = TRUE;
2929 }
2930
2931 /* Allocate the IRP */
2932 if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
2933 {
2934 ObDereferenceObject(FileObject);
2935 return STATUS_INSUFFICIENT_RESOURCES;
2936 }
2937
2938 /* Allocate the System Buffer */
2939 if (!(Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
2940 Length,
2941 TAG_SYSB)))
2942 {
2943 IoFreeIrp(Irp);
2944 ObDereferenceObject(FileObject);
2945 return STATUS_INSUFFICIENT_RESOURCES;
2946 }
2947
2948 /* Copy the data inside */
2949 MmSafeCopyFromUser(Irp->AssociatedIrp.SystemBuffer, FileInformation, Length);
2950
2951 /* Set up the IRP */
2952 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2953 Irp->RequestorMode = PreviousMode;
2954 Irp->UserIosb = IoStatusBlock;
2955 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
2956 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2957 Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
2958 Irp->Flags |= (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
2959
2960 /* Set up Stack Data */
2961 StackPtr = IoGetNextIrpStackLocation(Irp);
2962 StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION;
2963 StackPtr->FileObject = FileObject;
2964
2965 /* Set the Parameters */
2966 StackPtr->Parameters.SetFile.FileInformationClass = FileInformationClass;
2967 StackPtr->Parameters.SetFile.Length = Length;
2968
2969 /* Call the Driver */
2970 Status = IoCallDriver(DeviceObject, Irp);
2971 if (Status == STATUS_PENDING)
2972 {
2973 if (LocalEvent)
2974 {
2975 KeWaitForSingleObject(&Event,
2976 Executive,
2977 PreviousMode,
2978 FileObject->Flags & FO_ALERTABLE_IO,
2979 NULL);
2980 Status = IoStatusBlock->Status;
2981 }
2982 else
2983 {
2984 KeWaitForSingleObject(&FileObject->Event,
2985 Executive,
2986 PreviousMode,
2987 FileObject->Flags & FO_ALERTABLE_IO,
2988 NULL);
2989 Status = FileObject->FinalStatus;
2990 }
2991 }
2992
2993 /* Return the Status */
2994 return Status;
2995 }
2996
2997 /*
2998 * @unimplemented
2999 */
3000 NTSTATUS
3001 STDCALL
3002 NtSetQuotaInformationFile(HANDLE FileHandle,
3003 PIO_STATUS_BLOCK IoStatusBlock,
3004 PFILE_QUOTA_INFORMATION Buffer,
3005 ULONG BufferLength)
3006 {
3007 UNIMPLEMENTED;
3008 return STATUS_NOT_IMPLEMENTED;
3009 }
3010
3011 /*
3012 * @unimplemented
3013 */
3014 NTSTATUS
3015 STDCALL
3016 NtUnlockFile(IN HANDLE FileHandle,
3017 OUT PIO_STATUS_BLOCK IoStatusBlock,
3018 IN PLARGE_INTEGER ByteOffset,
3019 IN PLARGE_INTEGER Length,
3020 OUT PULONG Key OPTIONAL)
3021 {
3022 PFILE_OBJECT FileObject = NULL;
3023 PLARGE_INTEGER LocalLength = NULL;
3024 PIRP Irp = NULL;
3025 PIO_STACK_LOCATION StackPtr;
3026 PDEVICE_OBJECT DeviceObject;
3027 KEVENT Event;
3028 BOOLEAN LocalEvent = FALSE;
3029 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
3030 NTSTATUS Status = STATUS_SUCCESS;
3031 OBJECT_HANDLE_INFORMATION HandleInformation;
3032
3033 /* FIXME: instead of this, use SEH */
3034 if (!Length || !ByteOffset) return STATUS_INVALID_PARAMETER;
3035
3036 /* Get File Object */
3037 Status = ObReferenceObjectByHandle(FileHandle,
3038 0,
3039 IoFileObjectType,
3040 PreviousMode,
3041 (PVOID*)&FileObject,
3042 &HandleInformation);
3043 if (!NT_SUCCESS(Status)) return Status;
3044
3045 /* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
3046 if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_READ_DATA)))
3047 {
3048 DPRINT1("Invalid access rights\n");
3049 ObDereferenceObject(FileObject);
3050 return STATUS_ACCESS_DENIED;
3051 }
3052
3053 /* Check if this is a direct open or not */
3054 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
3055 {
3056 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
3057 }
3058 else
3059 {
3060 DeviceObject = IoGetRelatedDeviceObject(FileObject);
3061 }
3062
3063 /* Check if we should use Sync IO or not */
3064 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
3065 {
3066 /* Use File Object event */
3067 KeClearEvent(&FileObject->Event);
3068 }
3069 else
3070 {
3071 /* Use local event */
3072 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
3073 LocalEvent = TRUE;
3074 }
3075
3076 /* Allocate the IRP */
3077 if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
3078 {
3079 ObDereferenceObject(FileObject);
3080 return STATUS_INSUFFICIENT_RESOURCES;
3081 }
3082
3083 /* Allocate local buffer */
3084 LocalLength = ExAllocatePoolWithTag(NonPagedPool,
3085 sizeof(LARGE_INTEGER),
3086 TAG_LOCK);
3087 if (!LocalLength)
3088 {
3089 IoFreeIrp(Irp);
3090 ObDereferenceObject(FileObject);
3091 return STATUS_INSUFFICIENT_RESOURCES;
3092 }
3093 *LocalLength = *Length;
3094
3095 /* Set up the IRP */
3096 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
3097 Irp->RequestorMode = PreviousMode;
3098 Irp->UserIosb = IoStatusBlock;
3099 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
3100 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
3101 Irp->Tail.Overlay.OriginalFileObject = FileObject;
3102
3103 /* Set up Stack Data */
3104 StackPtr = IoGetNextIrpStackLocation(Irp);
3105 StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
3106 StackPtr->MinorFunction = IRP_MN_UNLOCK_SINGLE;
3107 StackPtr->FileObject = FileObject;
3108
3109 /* Set Parameters */
3110 StackPtr->Parameters.LockControl.Length = LocalLength;
3111 StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset;
3112 StackPtr->Parameters.LockControl.Key = Key ? *Key : 0;
3113
3114 /* Call the Driver */
3115 Status = IoCallDriver(DeviceObject, Irp);
3116 if (Status == STATUS_PENDING)
3117 {
3118 if (LocalEvent)
3119 {
3120 KeWaitForSingleObject(&Event,
3121 Executive,
3122 PreviousMode,
3123 FileObject->Flags & FO_ALERTABLE_IO,
3124 NULL);
3125 Status = IoStatusBlock->Status;
3126 }
3127 else
3128 {
3129 KeWaitForSingleObject(&FileObject->Event,
3130 Executive,
3131 PreviousMode,
3132 FileObject->Flags & FO_ALERTABLE_IO,
3133 NULL);
3134 Status = FileObject->FinalStatus;
3135 }
3136 }
3137
3138 /* Return the Status */
3139 return Status;
3140 }
3141
3142 /*
3143 * NAME EXPORTED
3144 * NtWriteFile
3145 *
3146 * DESCRIPTION
3147 *
3148 * ARGUMENTS
3149 *
3150 * RETURN VALUE
3151 *
3152 * REVISIONS
3153 *
3154 * @implemented
3155 */
3156 NTSTATUS
3157 STDCALL
3158 NtWriteFile (IN HANDLE FileHandle,
3159 IN HANDLE Event OPTIONAL,
3160 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
3161 IN PVOID ApcContext OPTIONAL,
3162 OUT PIO_STATUS_BLOCK IoStatusBlock,
3163 IN PVOID Buffer,
3164 IN ULONG Length,
3165 IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for asynch. operations! */
3166 IN PULONG Key OPTIONAL)
3167 {
3168 OBJECT_HANDLE_INFORMATION HandleInformation;
3169 NTSTATUS Status = STATUS_SUCCESS;
3170 PFILE_OBJECT FileObject;
3171 PIRP Irp = NULL;
3172 PDEVICE_OBJECT DeviceObject;
3173 PIO_STACK_LOCATION StackPtr;
3174 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
3175 BOOLEAN LocalEvent = FALSE;
3176 PKEVENT EventObject = NULL;
3177
3178 DPRINT("NtWriteFile(FileHandle 0x%p Buffer 0x%p Length %x ByteOffset 0x%p, "
3179 "IoStatusBlock 0x%p)\n", FileHandle, Buffer, Length, ByteOffset,
3180 IoStatusBlock);
3181
3182 /* Validate User-Mode Buffers */
3183 if(PreviousMode != KernelMode)
3184 {
3185 _SEH_TRY
3186 {
3187 #if 0
3188 ProbeForWrite(IoStatusBlock,
3189 sizeof(IO_STATUS_BLOCK),
3190 sizeof(ULONG));
3191
3192 ProbeForRead(Buffer,
3193 Length,
3194 sizeof(ULONG));
3195 #endif
3196 }
3197 _SEH_HANDLE
3198 {
3199 Status = _SEH_GetExceptionCode();
3200 }
3201 _SEH_END;
3202
3203 if(!NT_SUCCESS(Status)) return Status;
3204 }
3205
3206 /* Get File Object */
3207 Status = ObReferenceObjectByHandle(FileHandle,
3208 0,
3209 IoFileObjectType,
3210 PreviousMode,
3211 (PVOID*)&FileObject,
3212 &HandleInformation);
3213 if (!NT_SUCCESS(Status)) return Status;
3214
3215 /* Must have FILE_WRITE_DATA | FILE_APPEND_DATA access */
3216 if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)))
3217 {
3218 DPRINT1("Invalid access rights\n");
3219 ObDereferenceObject(FileObject);
3220 return STATUS_ACCESS_DENIED;
3221 }
3222
3223 /* Check if we got write Access */
3224 if (HandleInformation.GrantedAccess & FILE_WRITE_DATA)
3225 {
3226 /* Check the Byte Offset */
3227 if (!ByteOffset ||
3228 (ByteOffset->u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
3229 ByteOffset->u.HighPart == -1))
3230 {
3231 /* a valid ByteOffset is required if asynch. op. */
3232 if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
3233 {
3234 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
3235 ObDereferenceObject(FileObject);
3236 return STATUS_INVALID_PARAMETER;
3237 }
3238
3239 /* Use the Current Byte OFfset */
3240 ByteOffset = &FileObject->CurrentByteOffset;
3241 }
3242 }
3243 else if (HandleInformation.GrantedAccess & FILE_APPEND_DATA)
3244 {
3245 /* a valid ByteOffset is required if asynch. op. */
3246 if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
3247 {
3248 DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
3249 ObDereferenceObject(FileObject);
3250 return STATUS_INVALID_PARAMETER;
3251 }
3252
3253 /* Give the drivers somethign to understand */
3254 ByteOffset->u.LowPart = FILE_WRITE_TO_END_OF_FILE;
3255 ByteOffset->u.HighPart = 0xffffffff;
3256 }
3257
3258 /* Check if we got an event */
3259 if (Event)
3260 {
3261 /* Reference it */
3262 Status = ObReferenceObjectByHandle(Event,
3263 EVENT_MODIFY_STATE,
3264 ExEventObjectType,
3265 PreviousMode,
3266 (PVOID*)&EventObject,
3267 NULL);
3268 if (!NT_SUCCESS(Status))
3269 {
3270 ObDereferenceObject(FileObject);
3271 return Status;
3272 }
3273 KeClearEvent(EventObject);
3274 }
3275
3276 /* Check if this is a direct open or not */
3277 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
3278 {
3279 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
3280 }
3281 else
3282 {
3283 DeviceObject = IoGetRelatedDeviceObject(FileObject);
3284 }
3285
3286 /* Check if we should use Sync IO or not */
3287 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
3288 {
3289 /* Use File Object event */
3290 KeClearEvent(&FileObject->Event);
3291 }
3292 else
3293 {
3294 LocalEvent = TRUE;
3295 }
3296
3297 /* Build the IRP */
3298 _SEH_TRY
3299 {
3300 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
3301 DeviceObject,
3302 Buffer,
3303 Length,
3304 ByteOffset,
3305 EventObject,
3306 IoStatusBlock);
3307 if (Irp == NULL)
3308 {
3309 Status = STATUS_INSUFFICIENT_RESOURCES;
3310 }
3311 }
3312 _SEH_HANDLE
3313 {
3314 Status = _SEH_GetExceptionCode();
3315 }
3316 _SEH_END;
3317
3318 /* Cleanup on failure */
3319 if (!NT_SUCCESS(Status))
3320 {
3321 if (Event)
3322 {
3323 ObDereferenceObject(&EventObject);
3324 }
3325 ObDereferenceObject(FileObject);
3326 return Status;
3327 }
3328
3329 /* Set up IRP Data */
3330 Irp->Tail.Overlay.OriginalFileObject = FileObject;
3331 Irp->RequestorMode = PreviousMode;
3332 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
3333 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
3334 Irp->Flags |= IRP_WRITE_OPERATION;
3335 #if 0
3336 /* FIXME:
3337 * Vfat doesn't handle non cached files correctly.
3338 */
3339 if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) Irp->Flags |= IRP_NOCACHE;
3340 #endif
3341
3342 /* Setup Stack Data */
3343 StackPtr = IoGetNextIrpStackLocation(Irp);
3344 StackPtr->FileObject = FileObject;
3345 StackPtr->Parameters.Write.Key = Key ? *Key : 0;
3346 if (FileObject->Flags & FO_WRITE_THROUGH) StackPtr->Flags = SL_WRITE_THROUGH;
3347
3348 /* Call the Driver */
3349 Status = IoCallDriver(DeviceObject, Irp);
3350 if (Status == STATUS_PENDING)
3351 {
3352 if (!LocalEvent)
3353 {
3354 KeWaitForSingleObject(&FileObject->Event,
3355 Executive,
3356 PreviousMode,
3357 FileObject->Flags & FO_ALERTABLE_IO,
3358 NULL);
3359 Status = FileObject->FinalStatus;
3360 }
3361 }
3362
3363 /* Return the Status */
3364 return Status;
3365 }
3366
3367 /*
3368 * NAME EXPORTED
3369 * NtWriteFileGather
3370 *
3371 * DESCRIPTION
3372 *
3373 * ARGUMENTS
3374 *
3375 * RETURN VALUE
3376 *
3377 * REVISIONS
3378 */
3379 NTSTATUS
3380 STDCALL
3381 NtWriteFileGather(IN HANDLE FileHandle,
3382 IN HANDLE Event OPTIONAL,
3383 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
3384 IN PVOID UserApcContext OPTIONAL,
3385 OUT PIO_STATUS_BLOCK UserIoStatusBlock,
3386 IN FILE_SEGMENT_ELEMENT BufferDescription [],
3387 IN ULONG BufferLength,
3388 IN PLARGE_INTEGER ByteOffset,
3389 IN PULONG Key OPTIONAL)
3390 {
3391 UNIMPLEMENTED;
3392 return(STATUS_NOT_IMPLEMENTED);
3393 }
3394 /* EOF */