Don't allow setting menu for child windows in IntSetMenu.
[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 DPRINT("NtSetInformationFile(Handle 0x%p StatBlk 0x%p FileInfo 0x%p Length %d "
2813 "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
2814 Length, FileInformationClass);
2815
2816 if (PreviousMode != KernelMode)
2817 {
2818 _SEH_TRY
2819 {
2820 if (IoStatusBlock != NULL)
2821 {
2822 ProbeForWrite(IoStatusBlock,
2823 sizeof(IO_STATUS_BLOCK),
2824 sizeof(ULONG));
2825 }
2826
2827 if (Length != 0)
2828 {
2829 ProbeForRead(FileInformation,
2830 Length,
2831 1);
2832 }
2833 }
2834 _SEH_HANDLE
2835 {
2836 Status = _SEH_GetExceptionCode();
2837 }
2838 _SEH_END;
2839
2840 if (!NT_SUCCESS(Status))
2841 {
2842 return Status;
2843 }
2844 }
2845 else
2846 {
2847 ASSERT(IoStatusBlock != NULL);
2848 ASSERT(FileInformation != NULL);
2849 }
2850
2851 /* Get the file object from the file handle */
2852 Status = ObReferenceObjectByHandle(FileHandle,
2853 0,
2854 IoFileObjectType,
2855 PreviousMode,
2856 (PVOID *)&FileObject,
2857 &HandleInformation);
2858 if (!NT_SUCCESS(Status)) return Status;
2859
2860 /* Check information class specific access rights */
2861 switch (FileInformationClass)
2862 {
2863 case FileBasicInformation:
2864 if (!(HandleInformation.GrantedAccess & FILE_WRITE_ATTRIBUTES))
2865 Failed = TRUE;
2866 break;
2867
2868 case FileDispositionInformation:
2869 if (!(HandleInformation.GrantedAccess & DELETE))
2870 Failed = TRUE;
2871 break;
2872
2873 case FilePositionInformation:
2874 if (!(HandleInformation.GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA)) ||
2875 !(FileObject->Flags & FO_SYNCHRONOUS_IO))
2876 Failed = TRUE;
2877 break;
2878
2879 case FileEndOfFileInformation:
2880 if (!(HandleInformation.GrantedAccess & FILE_WRITE_DATA))
2881 Failed = TRUE;
2882 break;
2883
2884 default:
2885 break;
2886 }
2887
2888 if (Failed)
2889 {
2890 DPRINT1("NtSetInformationFile() returns STATUS_ACCESS_DENIED!\n");
2891 ObDereferenceObject(FileObject);
2892 return STATUS_ACCESS_DENIED;
2893 }
2894
2895 DPRINT("FileObject 0x%p\n", FileObject);
2896
2897 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
2898 /* Handle IO Completion Port quickly */
2899 if (FileInformationClass == FileCompletionInformation)
2900 {
2901 PVOID Queue;
2902 PFILE_COMPLETION_INFORMATION CompletionInfo = FileInformation;
2903 PIO_COMPLETION_CONTEXT Context;
2904
2905 if (Length < sizeof(FILE_COMPLETION_INFORMATION))
2906 {
2907 Status = STATUS_INFO_LENGTH_MISMATCH;
2908 }
2909 else
2910 {
2911 /* Reference the Port */
2912 Status = ObReferenceObjectByHandle(CompletionInfo->Port,
2913 IO_COMPLETION_MODIFY_STATE,
2914 IoCompletionType,
2915 PreviousMode,
2916 (PVOID*)&Queue,
2917 NULL);
2918 if (NT_SUCCESS(Status))
2919 {
2920 /* Allocate the Context */
2921 Context = ExAllocatePoolWithTag(PagedPool,
2922 sizeof(IO_COMPLETION_CONTEXT),
2923 TAG('I', 'o', 'C', 'p'));
2924
2925 /* Set the Data */
2926 Context->Key = CompletionInfo->Key;
2927 Context->Port = Queue;
2928 FileObject->CompletionContext = Context;
2929
2930 /* Dereference the Port now */
2931 ObDereferenceObject(Queue);
2932 }
2933 }
2934
2935 /* Complete the I/O */
2936 ObDereferenceObject(FileObject);
2937 return Status;
2938 }
2939
2940 /* Check if this is a direct open or not */
2941 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
2942 {
2943 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
2944 }
2945 else
2946 {
2947 DeviceObject = IoGetRelatedDeviceObject(FileObject);
2948 }
2949
2950 /* Check if we should use Sync IO or not */
2951 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
2952 {
2953 /* Use File Object event */
2954 KeClearEvent(&FileObject->Event);
2955 }
2956 else
2957 {
2958 /* Use local event */
2959 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
2960 LocalEvent = TRUE;
2961 }
2962
2963 /* Allocate the IRP */
2964 if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
2965 {
2966 ObDereferenceObject(FileObject);
2967 return STATUS_INSUFFICIENT_RESOURCES;
2968 }
2969
2970 /* Allocate the System Buffer */
2971 if (!(Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
2972 Length,
2973 TAG_SYSB)))
2974 {
2975 Status = STATUS_INSUFFICIENT_RESOURCES;
2976 goto failfreeirp;
2977 }
2978
2979 /* Copy the data inside */
2980 if (PreviousMode != KernelMode)
2981 {
2982 _SEH_TRY
2983 {
2984 /* no need to probe again */
2985 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
2986 FileInformation,
2987 Length);
2988 }
2989 _SEH_HANDLE
2990 {
2991 Status = _SEH_GetExceptionCode();
2992 }
2993 _SEH_END;
2994
2995 if (!NT_SUCCESS(Status))
2996 {
2997 ExFreePoolWithTag(Irp->AssociatedIrp.SystemBuffer,
2998 TAG_SYSB);
2999 Irp->AssociatedIrp.SystemBuffer = NULL;
3000 failfreeirp:
3001 IoFreeIrp(Irp);
3002 ObDereferenceObject(FileObject);
3003 return Status;
3004 }
3005 }
3006 else
3007 {
3008 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
3009 FileInformation,
3010 Length);
3011 }
3012
3013 /* Set up the IRP */
3014 Irp->Tail.Overlay.OriginalFileObject = FileObject;
3015 Irp->RequestorMode = PreviousMode;
3016 Irp->UserIosb = IoStatusBlock;
3017 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
3018 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
3019 Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
3020 Irp->Flags |= (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
3021
3022 /* Set up Stack Data */
3023 StackPtr = IoGetNextIrpStackLocation(Irp);
3024 StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION;
3025 StackPtr->FileObject = FileObject;
3026
3027 /* Set the Parameters */
3028 StackPtr->Parameters.SetFile.FileInformationClass = FileInformationClass;
3029 StackPtr->Parameters.SetFile.Length = Length;
3030
3031 /* Call the Driver */
3032 Status = IoCallDriver(DeviceObject, Irp);
3033 if (Status == STATUS_PENDING)
3034 {
3035 if (LocalEvent)
3036 {
3037 KeWaitForSingleObject(&Event,
3038 Executive,
3039 PreviousMode,
3040 FileObject->Flags & FO_ALERTABLE_IO,
3041 NULL);
3042 _SEH_TRY
3043 {
3044 Status = IoStatusBlock->Status;
3045 }
3046 _SEH_HANDLE
3047 {
3048 Status = _SEH_GetExceptionCode();
3049 }
3050 _SEH_END;
3051 }
3052 else
3053 {
3054 KeWaitForSingleObject(&FileObject->Event,
3055 Executive,
3056 PreviousMode,
3057 FileObject->Flags & FO_ALERTABLE_IO,
3058 NULL);
3059 _SEH_TRY
3060 {
3061 Status = FileObject->FinalStatus;
3062 }
3063 _SEH_HANDLE
3064 {
3065 Status = _SEH_GetExceptionCode();
3066 }
3067 _SEH_END;
3068 }
3069 }
3070
3071 /* Return the Status */
3072 return Status;
3073 }
3074
3075 /*
3076 * @unimplemented
3077 */
3078 NTSTATUS
3079 STDCALL
3080 NtSetQuotaInformationFile(HANDLE FileHandle,
3081 PIO_STATUS_BLOCK IoStatusBlock,
3082 PFILE_QUOTA_INFORMATION Buffer,
3083 ULONG BufferLength)
3084 {
3085 UNIMPLEMENTED;
3086 return STATUS_NOT_IMPLEMENTED;
3087 }
3088
3089 /*
3090 * @unimplemented
3091 */
3092 NTSTATUS
3093 STDCALL
3094 NtUnlockFile(IN HANDLE FileHandle,
3095 OUT PIO_STATUS_BLOCK IoStatusBlock,
3096 IN PLARGE_INTEGER ByteOffset,
3097 IN PLARGE_INTEGER Length,
3098 OUT PULONG Key OPTIONAL)
3099 {
3100 PFILE_OBJECT FileObject = NULL;
3101 PLARGE_INTEGER LocalLength = NULL;
3102 PIRP Irp = NULL;
3103 PIO_STACK_LOCATION StackPtr;
3104 PDEVICE_OBJECT DeviceObject;
3105 KEVENT Event;
3106 BOOLEAN LocalEvent = FALSE;
3107 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
3108 NTSTATUS Status = STATUS_SUCCESS;
3109 OBJECT_HANDLE_INFORMATION HandleInformation;
3110
3111 /* FIXME: instead of this, use SEH */
3112 if (!Length || !ByteOffset) return STATUS_INVALID_PARAMETER;
3113
3114 /* Get File Object */
3115 Status = ObReferenceObjectByHandle(FileHandle,
3116 0,
3117 IoFileObjectType,
3118 PreviousMode,
3119 (PVOID*)&FileObject,
3120 &HandleInformation);
3121 if (!NT_SUCCESS(Status)) return Status;
3122
3123 /* Must have FILE_READ_DATA | FILE_WRITE_DATA access */
3124 if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_READ_DATA)))
3125 {
3126 DPRINT1("Invalid access rights\n");
3127 ObDereferenceObject(FileObject);
3128 return STATUS_ACCESS_DENIED;
3129 }
3130
3131 /* Check if this is a direct open or not */
3132 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
3133 {
3134 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
3135 }
3136 else
3137 {
3138 DeviceObject = IoGetRelatedDeviceObject(FileObject);
3139 }
3140
3141 /* Check if we should use Sync IO or not */
3142 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
3143 {
3144 /* Use File Object event */
3145 KeClearEvent(&FileObject->Event);
3146 }
3147 else
3148 {
3149 /* Use local event */
3150 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
3151 LocalEvent = TRUE;
3152 }
3153
3154 /* Allocate the IRP */
3155 if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
3156 {
3157 ObDereferenceObject(FileObject);
3158 return STATUS_INSUFFICIENT_RESOURCES;
3159 }
3160
3161 /* Allocate local buffer */
3162 LocalLength = ExAllocatePoolWithTag(NonPagedPool,
3163 sizeof(LARGE_INTEGER),
3164 TAG_LOCK);
3165 if (!LocalLength)
3166 {
3167 IoFreeIrp(Irp);
3168 ObDereferenceObject(FileObject);
3169 return STATUS_INSUFFICIENT_RESOURCES;
3170 }
3171 *LocalLength = *Length;
3172
3173 /* Set up the IRP */
3174 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
3175 Irp->RequestorMode = PreviousMode;
3176 Irp->UserIosb = IoStatusBlock;
3177 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
3178 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
3179 Irp->Tail.Overlay.OriginalFileObject = FileObject;
3180
3181 /* Set up Stack Data */
3182 StackPtr = IoGetNextIrpStackLocation(Irp);
3183 StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
3184 StackPtr->MinorFunction = IRP_MN_UNLOCK_SINGLE;
3185 StackPtr->FileObject = FileObject;
3186
3187 /* Set Parameters */
3188 StackPtr->Parameters.LockControl.Length = LocalLength;
3189 StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset;
3190 StackPtr->Parameters.LockControl.Key = Key ? *Key : 0;
3191
3192 /* Call the Driver */
3193 Status = IoCallDriver(DeviceObject, Irp);
3194 if (Status == STATUS_PENDING)
3195 {
3196 if (LocalEvent)
3197 {
3198 KeWaitForSingleObject(&Event,
3199 Executive,
3200 PreviousMode,
3201 FileObject->Flags & FO_ALERTABLE_IO,
3202 NULL);
3203 Status = IoStatusBlock->Status;
3204 }
3205 else
3206 {
3207 KeWaitForSingleObject(&FileObject->Event,
3208 Executive,
3209 PreviousMode,
3210 FileObject->Flags & FO_ALERTABLE_IO,
3211 NULL);
3212 Status = FileObject->FinalStatus;
3213 }
3214 }
3215
3216 /* Return the Status */
3217 return Status;
3218 }
3219
3220 /*
3221 * NAME EXPORTED
3222 * NtWriteFile
3223 *
3224 * DESCRIPTION
3225 *
3226 * ARGUMENTS
3227 *
3228 * RETURN VALUE
3229 *
3230 * REVISIONS
3231 *
3232 * @implemented
3233 */
3234 NTSTATUS
3235 STDCALL
3236 NtWriteFile (IN HANDLE FileHandle,
3237 IN HANDLE Event OPTIONAL,
3238 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
3239 IN PVOID ApcContext OPTIONAL,
3240 OUT PIO_STATUS_BLOCK IoStatusBlock,
3241 IN PVOID Buffer,
3242 IN ULONG Length,
3243 IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for asynch. operations! */
3244 IN PULONG Key OPTIONAL)
3245 {
3246 OBJECT_HANDLE_INFORMATION HandleInformation;
3247 NTSTATUS Status = STATUS_SUCCESS;
3248 PFILE_OBJECT FileObject;
3249 PIRP Irp = NULL;
3250 PDEVICE_OBJECT DeviceObject;
3251 PIO_STACK_LOCATION StackPtr;
3252 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
3253 BOOLEAN LocalEvent = FALSE;
3254 PKEVENT EventObject = NULL;
3255
3256 DPRINT("NtWriteFile(FileHandle 0x%p Buffer 0x%p Length %x ByteOffset 0x%p, "
3257 "IoStatusBlock 0x%p)\n", FileHandle, Buffer, Length, ByteOffset,
3258 IoStatusBlock);
3259
3260 /* Validate User-Mode Buffers */
3261 if(PreviousMode != KernelMode)
3262 {
3263 _SEH_TRY
3264 {
3265 #if 0
3266 ProbeForWrite(IoStatusBlock,
3267 sizeof(IO_STATUS_BLOCK),
3268 sizeof(ULONG));
3269
3270 ProbeForRead(Buffer,
3271 Length,
3272 sizeof(ULONG));
3273 #endif
3274 }
3275 _SEH_HANDLE
3276 {
3277 Status = _SEH_GetExceptionCode();
3278 }
3279 _SEH_END;
3280
3281 if(!NT_SUCCESS(Status)) return Status;
3282 }
3283
3284 /* Get File Object */
3285 Status = ObReferenceObjectByHandle(FileHandle,
3286 0,
3287 IoFileObjectType,
3288 PreviousMode,
3289 (PVOID*)&FileObject,
3290 &HandleInformation);
3291 if (!NT_SUCCESS(Status)) return Status;
3292
3293 /* Must have FILE_WRITE_DATA | FILE_APPEND_DATA access */
3294 if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)))
3295 {
3296 DPRINT1("Invalid access rights\n");
3297 ObDereferenceObject(FileObject);
3298 return STATUS_ACCESS_DENIED;
3299 }
3300
3301 /* Check if we got write Access */
3302 if (HandleInformation.GrantedAccess & FILE_WRITE_DATA)
3303 {
3304 /* Check the Byte Offset */
3305 if (!ByteOffset ||
3306 (ByteOffset->u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
3307 ByteOffset->u.HighPart == -1))
3308 {
3309 /* a valid ByteOffset is required if asynch. op. */
3310 if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
3311 {
3312 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
3313 ObDereferenceObject(FileObject);
3314 return STATUS_INVALID_PARAMETER;
3315 }
3316
3317 /* Use the Current Byte OFfset */
3318 ByteOffset = &FileObject->CurrentByteOffset;
3319 }
3320 }
3321 else if (HandleInformation.GrantedAccess & FILE_APPEND_DATA)
3322 {
3323 /* a valid ByteOffset is required if asynch. op. */
3324 if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
3325 {
3326 DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
3327 ObDereferenceObject(FileObject);
3328 return STATUS_INVALID_PARAMETER;
3329 }
3330
3331 /* Give the drivers somethign to understand */
3332 ByteOffset->u.LowPart = FILE_WRITE_TO_END_OF_FILE;
3333 ByteOffset->u.HighPart = 0xffffffff;
3334 }
3335
3336 /* Check if we got an event */
3337 if (Event)
3338 {
3339 /* Reference it */
3340 Status = ObReferenceObjectByHandle(Event,
3341 EVENT_MODIFY_STATE,
3342 ExEventObjectType,
3343 PreviousMode,
3344 (PVOID*)&EventObject,
3345 NULL);
3346 if (!NT_SUCCESS(Status))
3347 {
3348 ObDereferenceObject(FileObject);
3349 return Status;
3350 }
3351 KeClearEvent(EventObject);
3352 }
3353
3354 /* Check if this is a direct open or not */
3355 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
3356 {
3357 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
3358 }
3359 else
3360 {
3361 DeviceObject = IoGetRelatedDeviceObject(FileObject);
3362 }
3363
3364 /* Check if we should use Sync IO or not */
3365 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
3366 {
3367 /* Use File Object event */
3368 KeClearEvent(&FileObject->Event);
3369 }
3370 else
3371 {
3372 LocalEvent = TRUE;
3373 }
3374
3375 /* Build the IRP */
3376 _SEH_TRY
3377 {
3378 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
3379 DeviceObject,
3380 Buffer,
3381 Length,
3382 ByteOffset,
3383 EventObject,
3384 IoStatusBlock);
3385 if (Irp == NULL)
3386 {
3387 Status = STATUS_INSUFFICIENT_RESOURCES;
3388 }
3389 }
3390 _SEH_HANDLE
3391 {
3392 Status = _SEH_GetExceptionCode();
3393 }
3394 _SEH_END;
3395
3396 /* Cleanup on failure */
3397 if (!NT_SUCCESS(Status))
3398 {
3399 if (Event)
3400 {
3401 ObDereferenceObject(&EventObject);
3402 }
3403 ObDereferenceObject(FileObject);
3404 return Status;
3405 }
3406
3407 /* Set up IRP Data */
3408 Irp->Tail.Overlay.OriginalFileObject = FileObject;
3409 Irp->RequestorMode = PreviousMode;
3410 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
3411 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
3412 Irp->Flags |= IRP_WRITE_OPERATION;
3413 #if 0
3414 /* FIXME:
3415 * Vfat doesn't handle non cached files correctly.
3416 */
3417 if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) Irp->Flags |= IRP_NOCACHE;
3418 #endif
3419
3420 /* Setup Stack Data */
3421 StackPtr = IoGetNextIrpStackLocation(Irp);
3422 StackPtr->FileObject = FileObject;
3423 StackPtr->Parameters.Write.Key = Key ? *Key : 0;
3424 if (FileObject->Flags & FO_WRITE_THROUGH) StackPtr->Flags = SL_WRITE_THROUGH;
3425
3426 /* Call the Driver */
3427 Status = IoCallDriver(DeviceObject, Irp);
3428 if (Status == STATUS_PENDING)
3429 {
3430 if (!LocalEvent)
3431 {
3432 KeWaitForSingleObject(&FileObject->Event,
3433 Executive,
3434 PreviousMode,
3435 FileObject->Flags & FO_ALERTABLE_IO,
3436 NULL);
3437 Status = FileObject->FinalStatus;
3438 }
3439 }
3440
3441 /* Return the Status */
3442 return Status;
3443 }
3444
3445 /*
3446 * NAME EXPORTED
3447 * NtWriteFileGather
3448 *
3449 * DESCRIPTION
3450 *
3451 * ARGUMENTS
3452 *
3453 * RETURN VALUE
3454 *
3455 * REVISIONS
3456 */
3457 NTSTATUS
3458 STDCALL
3459 NtWriteFileGather(IN HANDLE FileHandle,
3460 IN HANDLE Event OPTIONAL,
3461 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
3462 IN PVOID UserApcContext OPTIONAL,
3463 OUT PIO_STATUS_BLOCK UserIoStatusBlock,
3464 IN FILE_SEGMENT_ELEMENT BufferDescription [],
3465 IN ULONG BufferLength,
3466 IN PLARGE_INTEGER ByteOffset,
3467 IN PULONG Key OPTIONAL)
3468 {
3469 UNIMPLEMENTED;
3470 return(STATUS_NOT_IMPLEMENTED);
3471 }
3472 /* EOF */