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