fixed registry querying code in Ki386SetProcessorFeatures
[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 PEXTENDED_IO_STACK_LOCATION StackLoc;
755 IO_SECURITY_CONTEXT SecurityContext;
756 KPROCESSOR_MODE AccessMode;
757 HANDLE LocalHandle;
758 LARGE_INTEGER SafeAllocationSize;
759 PVOID SystemEaBuffer = NULL;
760 NTSTATUS Status = STATUS_SUCCESS;
761 AUX_DATA AuxData;
762 ACCESS_STATE AccessState;
763
764 DPRINT("IoCreateFile(FileHandle 0x%p, DesiredAccess %x, "
765 "ObjectAttributes 0x%p ObjectAttributes->ObjectName->Buffer %S)\n",
766 FileHandle,DesiredAccess,ObjectAttributes,
767 ObjectAttributes->ObjectName->Buffer);
768
769 ASSERT_IRQL(PASSIVE_LEVEL);
770
771 if (IoStatusBlock == NULL || FileHandle == NULL)
772 return STATUS_ACCESS_VIOLATION;
773
774 LocalHandle = 0;
775
776 if(Options & IO_NO_PARAMETER_CHECKING)
777 AccessMode = KernelMode;
778 else
779 AccessMode = ExGetPreviousMode();
780
781 if(AccessMode != KernelMode)
782 {
783 _SEH_TRY
784 {
785 ProbeForWriteHandle(FileHandle);
786 ProbeForWrite(IoStatusBlock,
787 sizeof(IO_STATUS_BLOCK),
788 sizeof(ULONG));
789 if(AllocationSize != NULL)
790 {
791 SafeAllocationSize = ProbeForReadLargeInteger(AllocationSize);
792 }
793 else
794 SafeAllocationSize.QuadPart = 0;
795
796 if(EaBuffer != NULL && EaLength > 0)
797 {
798 ProbeForRead(EaBuffer,
799 EaLength,
800 sizeof(ULONG));
801
802 /* marshal EaBuffer */
803 SystemEaBuffer = ExAllocatePool(NonPagedPool,
804 EaLength);
805 if(SystemEaBuffer == NULL)
806 {
807 Status = STATUS_INSUFFICIENT_RESOURCES;
808 _SEH_LEAVE;
809 }
810
811 RtlCopyMemory(SystemEaBuffer,
812 EaBuffer,
813 EaLength);
814 }
815 }
816 _SEH_HANDLE
817 {
818 Status = _SEH_GetExceptionCode();
819 }
820 _SEH_END;
821
822 if(!NT_SUCCESS(Status))
823 {
824 return Status;
825 }
826 }
827 else
828 {
829 if(AllocationSize != NULL)
830 SafeAllocationSize = *AllocationSize;
831 else
832 SafeAllocationSize.QuadPart = 0;
833
834 if(EaBuffer != NULL && EaLength > 0)
835 {
836 SystemEaBuffer = EaBuffer;
837 }
838 }
839
840 if(Options & IO_CHECK_CREATE_PARAMETERS)
841 {
842 DPRINT1("FIXME: IO_CHECK_CREATE_PARAMETERS not yet supported!\n");
843 }
844
845 /* First try to open an existing named object */
846 Status = ObOpenObjectByName(ObjectAttributes,
847 NULL,
848 NULL,
849 AccessMode,
850 DesiredAccess,
851 NULL,
852 &LocalHandle);
853
854 if (NT_SUCCESS(Status))
855 {
856 OBJECT_CREATE_INFORMATION ObjectCreateInfo;
857 OBJECT_ATTRIBUTES tmpObjectAttributes;
858 UNICODE_STRING ObjectName;
859
860 Status = ObReferenceObjectByHandle(LocalHandle,
861 DesiredAccess,
862 NULL,
863 AccessMode,
864 (PVOID*)&DeviceObject,
865 NULL);
866 ZwClose(LocalHandle);
867 if (!NT_SUCCESS(Status))
868 {
869 return Status;
870 }
871 if (BODY_TO_HEADER(DeviceObject)->Type != IoDeviceObjectType)
872 {
873 ObDereferenceObject (DeviceObject);
874 return STATUS_OBJECT_NAME_COLLISION;
875 }
876
877 Status = ObpCaptureObjectAttributes(ObjectAttributes,
878 AccessMode,
879 NULL,
880 &ObjectCreateInfo,
881 &ObjectName);
882 if (!NT_SUCCESS(Status))
883 {
884 ObDereferenceObject (DeviceObject);
885 return Status;
886 }
887
888 InitializeObjectAttributes(&tmpObjectAttributes,
889 NULL,
890 ObjectCreateInfo.Attributes & OBJ_INHERIT,
891 0,
892 NULL);
893 ObpReleaseCapturedAttributes(&ObjectCreateInfo);
894 if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
895
896
897 /* FIXME: wt... */
898 Status = ObCreateObject(KernelMode,
899 IoFileObjectType,
900 &tmpObjectAttributes,
901 KernelMode,
902 NULL,
903 sizeof(FILE_OBJECT),
904 0,
905 0,
906 (PVOID*)&FileObject);
907
908
909 /* Set File Object Data */
910 FileObject->DeviceObject = IoGetAttachedDevice(DeviceObject);
911 FileObject->Vpb = FileObject->DeviceObject->Vpb;
912
913 /* HACK */
914 FileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
915 DPRINT("%wZ\n", ObjectAttributes->ObjectName);
916
917 ObDereferenceObject (DeviceObject);
918 }
919
920
921 if (FileObject == NULL)
922 {
923 Status = ObCreateObject(AccessMode,
924 IoFileObjectType,
925 ObjectAttributes,
926 AccessMode,
927 NULL,
928 sizeof(FILE_OBJECT),
929 0,
930 0,
931 (PVOID*)&FileObject);
932 if (!NT_SUCCESS(Status))
933 {
934 DPRINT("ObCreateObject() failed! (Status %lx)\n", Status);
935 return Status;
936 }
937 }
938 RtlMapGenericMask(&DesiredAccess,
939 &BODY_TO_HEADER(FileObject)->Type->TypeInfo.GenericMapping);
940
941 Status = ObInsertObject ((PVOID)FileObject,
942 NULL,
943 DesiredAccess,
944 0,
945 NULL,
946 &LocalHandle);
947 if (!NT_SUCCESS(Status))
948 {
949 DPRINT("ObInsertObject() failed! (Status %lx)\n", Status);
950 ObMakeTemporaryObject(FileObject);
951 ObDereferenceObject (FileObject);
952 return Status;
953 }
954
955 if (CreateOptions & FILE_SYNCHRONOUS_IO_ALERT)
956 {
957 FileObject->Flags |= (FO_ALERTABLE_IO | FO_SYNCHRONOUS_IO);
958 }
959 if (CreateOptions & FILE_SYNCHRONOUS_IO_NONALERT)
960 {
961 FileObject->Flags |= FO_SYNCHRONOUS_IO;
962 }
963
964 if (CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING)
965 FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
966
967 /*
968 * FIXME: We should get the access state from Ob once this function becomes
969 * a parse routine once the Ob is refactored.
970 */
971 SeCreateAccessState(&AccessState, &AuxData, FILE_ALL_ACCESS, NULL);
972
973 SecurityContext.SecurityQos = NULL; /* ?? */
974 SecurityContext.AccessState = &AccessState;
975 SecurityContext.DesiredAccess = DesiredAccess;
976 SecurityContext.FullCreateOptions = 0; /* ?? */
977
978 KeInitializeEvent(&FileObject->Lock, SynchronizationEvent, TRUE);
979 KeInitializeEvent(&FileObject->Event, NotificationEvent, FALSE);
980
981 DPRINT("FileObject 0x%p\n", FileObject);
982 DPRINT("FileObject->DeviceObject 0x%p\n", FileObject->DeviceObject);
983 /*
984 * Create a new IRP to hand to
985 * the FS driver: this may fail
986 * due to resource shortage.
987 */
988 Irp = IoAllocateIrp(FileObject->DeviceObject->StackSize, FALSE);
989 if (Irp == NULL)
990 {
991 ZwClose(LocalHandle);
992 return STATUS_UNSUCCESSFUL;
993 }
994
995 //trigger FileObject/Event dereferencing
996 Irp->Tail.Overlay.OriginalFileObject = FileObject;
997 Irp->RequestorMode = AccessMode;
998 Irp->UserIosb = IoStatusBlock;
999 Irp->AssociatedIrp.SystemBuffer = SystemEaBuffer;
1000 Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
1001 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
1002 Irp->UserEvent = &FileObject->Event;
1003 Irp->Overlay.AllocationSize = SafeAllocationSize;
1004
1005 /*
1006 * Get the stack location for the new
1007 * IRP and prepare it.
1008 */
1009 StackLoc = (PEXTENDED_IO_STACK_LOCATION)IoGetNextIrpStackLocation(Irp);
1010 StackLoc->MinorFunction = 0;
1011 StackLoc->Flags = (UCHAR)Options;
1012 StackLoc->Control = 0;
1013 StackLoc->DeviceObject = FileObject->DeviceObject;
1014 StackLoc->FileObject = FileObject;
1015
1016 switch (CreateFileType)
1017 {
1018 default:
1019 case CreateFileTypeNone:
1020 StackLoc->MajorFunction = IRP_MJ_CREATE;
1021 StackLoc->Parameters.Create.SecurityContext = &SecurityContext;
1022 StackLoc->Parameters.Create.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
1023 StackLoc->Parameters.Create.Options |= (CreateDisposition << 24);
1024 StackLoc->Parameters.Create.FileAttributes = (USHORT)FileAttributes;
1025 StackLoc->Parameters.Create.ShareAccess = (USHORT)ShareAccess;
1026 StackLoc->Parameters.Create.EaLength = SystemEaBuffer != NULL ? EaLength : 0;
1027 break;
1028
1029 case CreateFileTypeNamedPipe:
1030 StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
1031 StackLoc->Parameters.CreatePipe.SecurityContext = &SecurityContext;
1032 StackLoc->Parameters.CreatePipe.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
1033 StackLoc->Parameters.CreatePipe.Options |= (CreateDisposition << 24);
1034 StackLoc->Parameters.CreatePipe.ShareAccess = (USHORT)ShareAccess;
1035 StackLoc->Parameters.CreatePipe.Parameters = ExtraCreateParameters;
1036 break;
1037
1038 case CreateFileTypeMailslot:
1039 StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
1040 StackLoc->Parameters.CreateMailslot.SecurityContext = &SecurityContext;
1041 StackLoc->Parameters.CreateMailslot.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
1042 StackLoc->Parameters.CreateMailslot.Options |= (CreateDisposition << 24);
1043 StackLoc->Parameters.CreateMailslot.ShareAccess = (USHORT)ShareAccess;
1044 StackLoc->Parameters.CreateMailslot.Parameters = ExtraCreateParameters;
1045 break;
1046 }
1047
1048 /*
1049 * Now call the driver and
1050 * possibly wait if it can
1051 * not complete the request
1052 * immediately.
1053 */
1054 Status = IofCallDriver(FileObject->DeviceObject, Irp );
1055 DPRINT("Status :%x\n", Status);
1056
1057 if (Status == STATUS_PENDING)
1058 {
1059 KeWaitForSingleObject(&FileObject->Event,
1060 Executive,
1061 AccessMode,
1062 FALSE,
1063 NULL);
1064 Status = IoStatusBlock->Status;
1065 }
1066 if (!NT_SUCCESS(Status))
1067 {
1068 DPRINT("Failing create request with status %x\n", Status);
1069 FileObject->DeviceObject = NULL;
1070 FileObject->Vpb = NULL;
1071
1072 ZwClose(LocalHandle);
1073 }
1074 else
1075 {
1076 _SEH_TRY
1077 {
1078 *FileHandle = LocalHandle;
1079 }
1080 _SEH_HANDLE
1081 {
1082 Status = _SEH_GetExceptionCode();
1083 }
1084 _SEH_END;
1085 }
1086
1087 /* cleanup EABuffer if captured */
1088 if(AccessMode != KernelMode && SystemEaBuffer != NULL)
1089 {
1090 ExFreePool(SystemEaBuffer);
1091 }
1092
1093 ASSERT_IRQL(PASSIVE_LEVEL);
1094
1095 DPRINT("Finished IoCreateFile() (*FileHandle) 0x%p\n", (*FileHandle));
1096
1097 return Status;
1098 }
1099
1100 /*
1101 * @unimplemented
1102 */
1103 NTSTATUS
1104 STDCALL
1105 IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle,
1106 IN ACCESS_MASK DesiredAccess,
1107 IN POBJECT_ATTRIBUTES ObjectAttributes,
1108 OUT PIO_STATUS_BLOCK IoStatusBlock,
1109 IN PLARGE_INTEGER AllocationSize OPTIONAL,
1110 IN ULONG FileAttributes,
1111 IN ULONG ShareAccess,
1112 IN ULONG Disposition,
1113 IN ULONG CreateOptions,
1114 IN PVOID EaBuffer OPTIONAL,
1115 IN ULONG EaLength,
1116 IN CREATE_FILE_TYPE CreateFileType,
1117 IN PVOID ExtraCreateParameters OPTIONAL,
1118 IN ULONG Options,
1119 IN PVOID DeviceObject)
1120 {
1121 UNIMPLEMENTED;
1122 return STATUS_NOT_IMPLEMENTED;
1123 }
1124
1125 /*
1126 * NAME EXPORTED
1127 * IoCreateStreamFileObject@8
1128 *
1129 * DESCRIPTION
1130 *
1131 * ARGUMENTS
1132 * FileObject
1133 * ?
1134 *
1135 * DeviceObject
1136 * ?
1137 *
1138 * RETURN VALUE
1139 *
1140 * NOTE
1141 *
1142 * REVISIONS
1143 *
1144 * @implemented
1145 */
1146 PFILE_OBJECT
1147 STDCALL
1148 IoCreateStreamFileObject(PFILE_OBJECT FileObject,
1149 PDEVICE_OBJECT DeviceObject)
1150 {
1151 PFILE_OBJECT CreatedFileObject;
1152 NTSTATUS Status;
1153
1154 /* FIXME: This function should call ObInsertObject. The "Lite" version
1155 doesnt. This function is also called from IoCreateFile for some
1156 reason. These hacks need to be removed.
1157 */
1158
1159 DPRINT("IoCreateStreamFileObject(FileObject 0x%p, DeviceObject 0x%p)\n",
1160 FileObject, DeviceObject);
1161 PAGED_CODE();
1162
1163 /* Create the File Object */
1164 Status = ObCreateObject(KernelMode,
1165 IoFileObjectType,
1166 NULL,
1167 KernelMode,
1168 NULL,
1169 sizeof(FILE_OBJECT),
1170 0,
1171 0,
1172 (PVOID*)&CreatedFileObject);
1173 if (!NT_SUCCESS(Status))
1174 {
1175 DPRINT1("Could not create FileObject\n");
1176 return (NULL);
1177 }
1178
1179 /* Choose Device Object */
1180 if (FileObject) DeviceObject = FileObject->DeviceObject;
1181 DPRINT("DeviceObject 0x%p\n", DeviceObject);
1182
1183 /* HACK */
1184 DeviceObject = IoGetAttachedDevice(DeviceObject);
1185
1186 /* Set File Object Data */
1187 CreatedFileObject->DeviceObject = DeviceObject;
1188 CreatedFileObject->Vpb = DeviceObject->Vpb;
1189 CreatedFileObject->Type = IO_TYPE_FILE;
1190 CreatedFileObject->Flags |= FO_STREAM_FILE;
1191
1192 /* Initialize Lock and Event */
1193 KeInitializeEvent(&CreatedFileObject->Event, NotificationEvent, FALSE);
1194 KeInitializeEvent(&CreatedFileObject->Lock, SynchronizationEvent, TRUE);
1195
1196 /* Return file */
1197 return CreatedFileObject;
1198 }
1199
1200 /*
1201 * @unimplemented
1202 */
1203 PFILE_OBJECT
1204 STDCALL
1205 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL,
1206 IN PDEVICE_OBJECT DeviceObject OPTIONAL,
1207 OUT PHANDLE FileObjectHandle OPTIONAL)
1208 {
1209 UNIMPLEMENTED;
1210 return 0;
1211 }
1212
1213 /*
1214 * @unimplemented
1215 */
1216 PFILE_OBJECT
1217 STDCALL
1218 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL,
1219 IN PDEVICE_OBJECT DeviceObject OPTIONAL)
1220 {
1221 UNIMPLEMENTED;
1222 return 0;
1223 }
1224
1225 /*
1226 * @implemented
1227 */
1228 PGENERIC_MAPPING
1229 STDCALL
1230 IoGetFileObjectGenericMapping(VOID)
1231 {
1232 return &IopFileMapping;
1233 }
1234
1235 /*
1236 * @implemented
1237 */
1238 BOOLEAN
1239 STDCALL
1240 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject)
1241 {
1242 /* Return the flag status */
1243 return (FileObject->Flags & FO_REMOTE_ORIGIN);
1244 }
1245
1246 /*
1247 * @unimplemented
1248 */
1249 NTSTATUS
1250 STDCALL
1251 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject,
1252 OUT POBJECT_NAME_INFORMATION *ObjectNameInformation)
1253 {
1254 UNIMPLEMENTED;
1255 return STATUS_NOT_IMPLEMENTED;
1256 }
1257
1258 /*
1259 * @implemented
1260 */
1261 NTSTATUS
1262 STDCALL
1263 IoQueryFileInformation(IN PFILE_OBJECT FileObject,
1264 IN FILE_INFORMATION_CLASS FileInformationClass,
1265 IN ULONG Length,
1266 OUT PVOID FileInformation,
1267 OUT PULONG ReturnedLength)
1268 {
1269 IO_STATUS_BLOCK IoStatusBlock;
1270 PIRP Irp;
1271 PDEVICE_OBJECT DeviceObject;
1272 PIO_STACK_LOCATION StackPtr;
1273 BOOLEAN LocalEvent = FALSE;
1274 KEVENT Event;
1275 NTSTATUS Status;
1276
1277 ASSERT(FileInformation != NULL);
1278
1279 Status = ObReferenceObjectByPointer(FileObject,
1280 FILE_READ_ATTRIBUTES,
1281 IoFileObjectType,
1282 KernelMode);
1283 if (!NT_SUCCESS(Status)) return(Status);
1284
1285 DPRINT("FileObject 0x%p\n", FileObject);
1286
1287 /* Get the Device Object */
1288 DeviceObject = IoGetRelatedDeviceObject(FileObject);
1289
1290 /* Check if we should use Sync IO or not */
1291 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
1292 {
1293 /* Use File Object event */
1294 KeClearEvent(&FileObject->Event);
1295 }
1296 else
1297 {
1298 /* Use local event */
1299 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
1300 LocalEvent = TRUE;
1301 }
1302
1303 /* Allocate the IRP */
1304 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
1305
1306 /* Set the IRP */
1307 Irp->Tail.Overlay.OriginalFileObject = FileObject;
1308 Irp->RequestorMode = KernelMode;
1309 Irp->AssociatedIrp.SystemBuffer = FileInformation;
1310 Irp->UserIosb = &IoStatusBlock;
1311 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
1312 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
1313 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
1314
1315 /* Set the Stack Data */
1316 StackPtr = IoGetNextIrpStackLocation(Irp);
1317 StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
1318 StackPtr->FileObject = FileObject;
1319
1320 /* Set Parameters */
1321 StackPtr->Parameters.QueryFile.FileInformationClass = FileInformationClass;
1322 StackPtr->Parameters.QueryFile.Length = Length;
1323
1324 /* Call the Driver */
1325 Status = IoCallDriver(FileObject->DeviceObject, Irp);
1326
1327 if (Status == STATUS_PENDING)
1328 {
1329 if (LocalEvent)
1330 {
1331 KeWaitForSingleObject(&Event,
1332 Executive,
1333 KernelMode,
1334 FileObject->Flags & FO_ALERTABLE_IO,
1335 NULL);
1336 Status = IoStatusBlock.Status;
1337 }
1338 else
1339 {
1340 KeWaitForSingleObject(&FileObject->Event,
1341 Executive,
1342 KernelMode,
1343 FileObject->Flags & FO_ALERTABLE_IO,
1344 NULL);
1345 Status = FileObject->FinalStatus;
1346 }
1347 }
1348
1349
1350 /* Return the Length and Status. ReturnedLength is NOT optional */
1351 *ReturnedLength = IoStatusBlock.Information;
1352 return Status;
1353 }
1354
1355 /*
1356 * @unimplemented
1357 */
1358 NTSTATUS
1359 STDCALL
1360 IoSetFileOrigin(IN PFILE_OBJECT FileObject,
1361 IN BOOLEAN Remote)
1362 {
1363 UNIMPLEMENTED;
1364 return STATUS_NOT_IMPLEMENTED;
1365 }
1366
1367 /**
1368 * @name NtCancelIoFile
1369 *
1370 * Cancel all pending I/O operations in the current thread for specified
1371 * file object.
1372 *
1373 * @param FileHandle
1374 * Handle to file object to cancel requests for. No specific
1375 * access rights are needed.
1376 * @param IoStatusBlock
1377 * Pointer to status block which is filled with final completition
1378 * status on successful return.
1379 *
1380 * @return Status.
1381 *
1382 * @implemented
1383 */
1384 NTSTATUS
1385 STDCALL
1386 NtCancelIoFile(IN HANDLE FileHandle,
1387 OUT PIO_STATUS_BLOCK IoStatusBlock)
1388 {
1389 PFILE_OBJECT FileObject;
1390 PETHREAD Thread;
1391 PIRP Irp;
1392 KIRQL OldIrql;
1393 BOOLEAN OurIrpsInList = FALSE;
1394 LARGE_INTEGER Interval;
1395 KPROCESSOR_MODE PreviousMode;
1396 NTSTATUS Status = STATUS_SUCCESS;
1397
1398 PAGED_CODE();
1399
1400 PreviousMode = KeGetPreviousMode();
1401
1402 if (PreviousMode != KernelMode)
1403 {
1404 _SEH_TRY
1405 {
1406 ProbeForWrite(IoStatusBlock,
1407 sizeof(IO_STATUS_BLOCK),
1408 sizeof(ULONG));
1409 }
1410 _SEH_HANDLE
1411 {
1412 Status = _SEH_GetExceptionCode();
1413 }
1414 _SEH_END;
1415
1416 if (!NT_SUCCESS(Status)) return Status;
1417 }
1418
1419 Status = ObReferenceObjectByHandle(FileHandle,
1420 0,
1421 IoFileObjectType,
1422 PreviousMode,
1423 (PVOID*)&FileObject,
1424 NULL);
1425 if (!NT_SUCCESS(Status))
1426 return Status;
1427
1428 /* IRP cancellations are synchronized at APC_LEVEL. */
1429 OldIrql = KfRaiseIrql(APC_LEVEL);
1430
1431 /*
1432 * Walk the list of active IRPs and cancel the ones that belong to
1433 * our file object.
1434 */
1435
1436 Thread = PsGetCurrentThread();
1437
1438 LIST_FOR_EACH(Irp, &Thread->IrpList, IRP, ThreadListEntry)
1439 {
1440 if (Irp->Tail.Overlay.OriginalFileObject == FileObject)
1441 {
1442 IoCancelIrp(Irp);
1443 /* Don't break here, we want to cancel all IRPs for the file object. */
1444 OurIrpsInList = TRUE;
1445 }
1446 }
1447
1448 KfLowerIrql(OldIrql);
1449
1450 while (OurIrpsInList)
1451 {
1452 OurIrpsInList = FALSE;
1453
1454 /* Wait a short while and then look if all our IRPs were completed. */
1455 Interval.QuadPart = -1000000; /* 100 milliseconds */
1456 KeDelayExecutionThread(KernelMode, FALSE, &Interval);
1457
1458 OldIrql = KfRaiseIrql(APC_LEVEL);
1459
1460 /*
1461 * Look in the list if all IRPs for the specified file object
1462 * are completed (or cancelled). If someone sends a new IRP
1463 * for our file object while we're here we can happily loop
1464 * forever.
1465 */
1466
1467 LIST_FOR_EACH(Irp, &Thread->IrpList, IRP, ThreadListEntry)
1468 {
1469 if (Irp->Tail.Overlay.OriginalFileObject == FileObject)
1470 {
1471 OurIrpsInList = TRUE;
1472 break;
1473 }
1474 }
1475
1476 KfLowerIrql(OldIrql);
1477 }
1478
1479 _SEH_TRY
1480 {
1481 IoStatusBlock->Status = STATUS_SUCCESS;
1482 IoStatusBlock->Information = 0;
1483 Status = STATUS_SUCCESS;
1484 }
1485 _SEH_HANDLE
1486 {
1487 Status = STATUS_UNSUCCESSFUL;
1488 }
1489 _SEH_END;
1490
1491 ObDereferenceObject(FileObject);
1492
1493 return Status;
1494 }
1495
1496 /*
1497 * NAME EXPORTED
1498 * NtCreateFile@44
1499 *
1500 * DESCRIPTION
1501 * Entry point to call IoCreateFile with
1502 * default parameters.
1503 *
1504 * ARGUMENTS
1505 * See IoCreateFile.
1506 *
1507 * RETURN VALUE
1508 * See IoCreateFile.
1509 *
1510 * REVISIONS
1511 * 2000-03-25 (ea)
1512 * Code originally in NtCreateFile moved in IoCreateFile.
1513 *
1514 * @implemented
1515 */
1516 NTSTATUS
1517 STDCALL
1518 NtCreateFile(PHANDLE FileHandle,
1519 ACCESS_MASK DesiredAccess,
1520 POBJECT_ATTRIBUTES ObjectAttributes,
1521 PIO_STATUS_BLOCK IoStatusBlock,
1522 PLARGE_INTEGER AllocateSize,
1523 ULONG FileAttributes,
1524 ULONG ShareAccess,
1525 ULONG CreateDisposition,
1526 ULONG CreateOptions,
1527 PVOID EaBuffer,
1528 ULONG EaLength)
1529 {
1530 /* Call the I/O Function */
1531 return IoCreateFile(FileHandle,
1532 DesiredAccess,
1533 ObjectAttributes,
1534 IoStatusBlock,
1535 AllocateSize,
1536 FileAttributes,
1537 ShareAccess,
1538 CreateDisposition,
1539 CreateOptions,
1540 EaBuffer,
1541 EaLength,
1542 CreateFileTypeNone,
1543 NULL,
1544 0);
1545 }
1546
1547 NTSTATUS
1548 STDCALL
1549 NtCreateMailslotFile(OUT PHANDLE FileHandle,
1550 IN ACCESS_MASK DesiredAccess,
1551 IN POBJECT_ATTRIBUTES ObjectAttributes,
1552 OUT PIO_STATUS_BLOCK IoStatusBlock,
1553 IN ULONG CreateOptions,
1554 IN ULONG MailslotQuota,
1555 IN ULONG MaxMessageSize,
1556 IN PLARGE_INTEGER TimeOut)
1557 {
1558 MAILSLOT_CREATE_PARAMETERS Buffer;
1559
1560 DPRINT("NtCreateMailslotFile(FileHandle 0x%p, DesiredAccess %x, "
1561 "ObjectAttributes 0x%p)\n",
1562 FileHandle,DesiredAccess,ObjectAttributes);
1563
1564 PAGED_CODE();
1565
1566 /* Check for Timeout */
1567 if (TimeOut != NULL)
1568 {
1569 if (KeGetPreviousMode() != KernelMode)
1570 {
1571 NTSTATUS Status = STATUS_SUCCESS;
1572
1573 _SEH_TRY
1574 {
1575 Buffer.ReadTimeout = ProbeForReadLargeInteger(TimeOut);
1576 }
1577 _SEH_HANDLE
1578 {
1579 Status = _SEH_GetExceptionCode();
1580 }
1581 _SEH_END;
1582
1583 if (!NT_SUCCESS(Status)) return Status;
1584 }
1585 else
1586 {
1587 Buffer.ReadTimeout = *TimeOut;
1588 }
1589
1590 Buffer.TimeoutSpecified = TRUE;
1591 }
1592 else
1593 {
1594 Buffer.TimeoutSpecified = FALSE;
1595 }
1596
1597 /* Set Settings */
1598 Buffer.MailslotQuota = MailslotQuota;
1599 Buffer.MaximumMessageSize = MaxMessageSize;
1600
1601 /* Call I/O */
1602 return IoCreateFile(FileHandle,
1603 DesiredAccess,
1604 ObjectAttributes,
1605 IoStatusBlock,
1606 NULL,
1607 FILE_ATTRIBUTE_NORMAL,
1608 FILE_SHARE_READ | FILE_SHARE_WRITE,
1609 FILE_CREATE,
1610 CreateOptions,
1611 NULL,
1612 0,
1613 CreateFileTypeMailslot,
1614 (PVOID)&Buffer,
1615 0);
1616 }
1617
1618 NTSTATUS
1619 STDCALL
1620 NtCreateNamedPipeFile(PHANDLE FileHandle,
1621 ACCESS_MASK DesiredAccess,
1622 POBJECT_ATTRIBUTES ObjectAttributes,
1623 PIO_STATUS_BLOCK IoStatusBlock,
1624 ULONG ShareAccess,
1625 ULONG CreateDisposition,
1626 ULONG CreateOptions,
1627 ULONG NamedPipeType,
1628 ULONG ReadMode,
1629 ULONG CompletionMode,
1630 ULONG MaximumInstances,
1631 ULONG InboundQuota,
1632 ULONG OutboundQuota,
1633 PLARGE_INTEGER DefaultTimeout)
1634 {
1635 NAMED_PIPE_CREATE_PARAMETERS Buffer;
1636
1637 DPRINT("NtCreateNamedPipeFile(FileHandle 0x%p, DesiredAccess %x, "
1638 "ObjectAttributes 0x%p)\n",
1639 FileHandle,DesiredAccess,ObjectAttributes);
1640
1641 PAGED_CODE();
1642
1643 /* Check for Timeout */
1644 if (DefaultTimeout != NULL)
1645 {
1646 if (KeGetPreviousMode() != KernelMode)
1647 {
1648 NTSTATUS Status = STATUS_SUCCESS;
1649
1650 _SEH_TRY
1651 {
1652 Buffer.DefaultTimeout = ProbeForReadLargeInteger(DefaultTimeout);
1653 }
1654 _SEH_HANDLE
1655 {
1656 Status = _SEH_GetExceptionCode();
1657 }
1658 _SEH_END;
1659
1660 if (!NT_SUCCESS(Status)) return Status;
1661 }
1662 else
1663 {
1664 Buffer.DefaultTimeout = *DefaultTimeout;
1665 }
1666
1667 Buffer.TimeoutSpecified = TRUE;
1668 }
1669 else
1670 Buffer.TimeoutSpecified = FALSE;
1671
1672 /* Set Settings */
1673 Buffer.NamedPipeType = NamedPipeType;
1674 Buffer.ReadMode = ReadMode;
1675 Buffer.CompletionMode = CompletionMode;
1676 Buffer.MaximumInstances = MaximumInstances;
1677 Buffer.InboundQuota = InboundQuota;
1678 Buffer.OutboundQuota = OutboundQuota;
1679
1680 /* Call I/O */
1681 return IoCreateFile(FileHandle,
1682 DesiredAccess,
1683 ObjectAttributes,
1684 IoStatusBlock,
1685 NULL,
1686 FILE_ATTRIBUTE_NORMAL,
1687 ShareAccess,
1688 CreateDisposition,
1689 CreateOptions,
1690 NULL,
1691 0,
1692 CreateFileTypeNamedPipe,
1693 (PVOID)&Buffer,
1694 0);
1695 }
1696
1697 /*
1698 * NAME EXPORTED
1699 * NtDeleteFile@4
1700 *
1701 * DESCRIPTION
1702 *
1703 * ARGUMENTS
1704 * ObjectAttributes
1705 * ?
1706 *
1707 * RETURN VALUE
1708 *
1709 * REVISIONS
1710 *
1711 * @unimplemented
1712 */
1713 NTSTATUS
1714 STDCALL
1715 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes)
1716 {
1717 UNIMPLEMENTED;
1718 return(STATUS_NOT_IMPLEMENTED);
1719 }
1720
1721 /*
1722 * @implemented
1723 */
1724 NTSTATUS
1725 STDCALL
1726 NtDeviceIoControlFile(IN HANDLE DeviceHandle,
1727 IN HANDLE Event OPTIONAL,
1728 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
1729 IN PVOID UserApcContext OPTIONAL,
1730 OUT PIO_STATUS_BLOCK IoStatusBlock,
1731 IN ULONG IoControlCode,
1732 IN PVOID InputBuffer,
1733 IN ULONG InputBufferLength OPTIONAL,
1734 OUT PVOID OutputBuffer,
1735 IN ULONG OutputBufferLength OPTIONAL)
1736 {
1737 /* Call the Generic Function */
1738 return IopDeviceFsIoControl(DeviceHandle,
1739 Event,
1740 UserApcRoutine,
1741 UserApcContext,
1742 IoStatusBlock,
1743 IoControlCode,
1744 InputBuffer,
1745 InputBufferLength,
1746 OutputBuffer,
1747 OutputBufferLength,
1748 TRUE);
1749 }
1750
1751 /*
1752 * @implemented
1753 */
1754 NTSTATUS
1755 STDCALL
1756 NtFsControlFile(IN HANDLE DeviceHandle,
1757 IN HANDLE Event OPTIONAL,
1758 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
1759 IN PVOID UserApcContext OPTIONAL,
1760 OUT PIO_STATUS_BLOCK IoStatusBlock,
1761 IN ULONG IoControlCode,
1762 IN PVOID InputBuffer,
1763 IN ULONG InputBufferLength OPTIONAL,
1764 OUT PVOID OutputBuffer,
1765 IN ULONG OutputBufferLength OPTIONAL)
1766 {
1767 return IopDeviceFsIoControl(DeviceHandle,
1768 Event,
1769 UserApcRoutine,
1770 UserApcContext,
1771 IoStatusBlock,
1772 IoControlCode,
1773 InputBuffer,
1774 InputBufferLength,
1775 OutputBuffer,
1776 OutputBufferLength,
1777 FALSE);
1778 }
1779
1780 NTSTATUS
1781 STDCALL
1782 NtFlushWriteBuffer(VOID)
1783 {
1784 PAGED_CODE();
1785
1786 KeFlushWriteBuffer();
1787 return STATUS_SUCCESS;
1788 }
1789
1790 /*
1791 * FUNCTION: Flushes cached file data to disk
1792 * ARGUMENTS:
1793 * FileHandle = Points to the file
1794 * IoStatusBlock = Caller must supply storage to receive the result of
1795 * the flush buffers operation. The information field is
1796 * set to number of bytes flushed to disk.
1797 * RETURNS: Status
1798 * REMARKS: This function maps to the win32 FlushFileBuffers
1799 */
1800 NTSTATUS
1801 STDCALL
1802 NtFlushBuffersFile(IN HANDLE FileHandle,
1803 OUT PIO_STATUS_BLOCK IoStatusBlock)
1804 {
1805 PFILE_OBJECT FileObject = NULL;
1806 PIRP Irp;
1807 PIO_STACK_LOCATION StackPtr;
1808 NTSTATUS Status = STATUS_SUCCESS;
1809 PDEVICE_OBJECT DeviceObject;
1810 KEVENT Event;
1811 BOOLEAN LocalEvent = FALSE;
1812 ACCESS_MASK DesiredAccess = FILE_WRITE_DATA;
1813 OBJECT_HANDLE_INFORMATION ObjectHandleInfo;
1814 KPROCESSOR_MODE PreviousMode;
1815
1816 PAGED_CODE();
1817
1818 PreviousMode = KeGetPreviousMode();
1819
1820 if (PreviousMode != KernelMode)
1821 {
1822 _SEH_TRY
1823 {
1824 ProbeForWrite(IoStatusBlock,
1825 sizeof(IO_STATUS_BLOCK),
1826 sizeof(ULONG));
1827 }
1828 _SEH_HANDLE
1829 {
1830 Status = _SEH_GetExceptionCode();
1831 }
1832 _SEH_END;
1833
1834 if (!NT_SUCCESS(Status)) return Status;
1835 }
1836
1837 /* Get the File Object */
1838 Status = ObReferenceObjectByHandle(FileHandle,
1839 0,
1840 IoFileObjectType,
1841 PreviousMode,
1842 (PVOID*)&FileObject,
1843 &ObjectHandleInfo);
1844 if (!NT_SUCCESS(Status)) return(Status);
1845
1846 /* check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
1847 granted. However, if this is a named pipe, make sure we don't ask for
1848 FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
1849 access right! */
1850 if (!(FileObject->Flags & FO_NAMED_PIPE))
1851 DesiredAccess |= FILE_APPEND_DATA;
1852 if (!RtlAreAnyAccessesGranted(ObjectHandleInfo.GrantedAccess,
1853 DesiredAccess))
1854 {
1855 ObDereferenceObject(FileObject);
1856 return STATUS_ACCESS_DENIED;
1857 }
1858
1859 /* Check if this is a direct open or not */
1860 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
1861 {
1862 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
1863 }
1864 else
1865 {
1866 DeviceObject = IoGetRelatedDeviceObject(FileObject);
1867 }
1868
1869 /* Check if we should use Sync IO or not */
1870 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
1871 {
1872 /* Use File Object event */
1873 KeClearEvent(&FileObject->Event);
1874 }
1875 else
1876 {
1877 /* Use local event */
1878 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
1879 LocalEvent = TRUE;
1880 }
1881
1882 /* Allocate the IRP */
1883 if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
1884 {
1885 ObDereferenceObject(FileObject);
1886 return STATUS_INSUFFICIENT_RESOURCES;
1887 }
1888
1889 /* Set up the IRP */
1890 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
1891 Irp->RequestorMode = PreviousMode;
1892 Irp->UserIosb = IoStatusBlock;
1893 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
1894 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
1895 Irp->Tail.Overlay.OriginalFileObject = FileObject;
1896
1897 /* Set up Stack Data */
1898 StackPtr = IoGetNextIrpStackLocation(Irp);
1899 StackPtr->MajorFunction = IRP_MJ_FLUSH_BUFFERS;
1900 StackPtr->FileObject = FileObject;
1901
1902 /* Call the Driver */
1903 Status = IoCallDriver(DeviceObject, Irp);
1904 if (Status == STATUS_PENDING)
1905 {
1906 if (LocalEvent)
1907 {
1908 KeWaitForSingleObject(&Event,
1909 Executive,
1910 PreviousMode,
1911 FileObject->Flags & FO_ALERTABLE_IO,
1912 NULL);
1913 Status = IoStatusBlock->Status;
1914 }
1915 else
1916 {
1917 KeWaitForSingleObject(&FileObject->Event,
1918 Executive,
1919 PreviousMode,
1920 FileObject->Flags & FO_ALERTABLE_IO,
1921 NULL);
1922 Status = FileObject->FinalStatus;
1923 }
1924 }
1925
1926 /* Return the Status */
1927 return Status;
1928 }
1929
1930 /*
1931 * @implemented
1932 */
1933 NTSTATUS
1934 STDCALL
1935 NtNotifyChangeDirectoryFile(IN HANDLE FileHandle,
1936 IN HANDLE Event OPTIONAL,
1937 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
1938 IN PVOID ApcContext OPTIONAL,
1939 OUT PIO_STATUS_BLOCK IoStatusBlock,
1940 OUT PVOID Buffer,
1941 IN ULONG BufferSize,
1942 IN ULONG CompletionFilter,
1943 IN BOOLEAN WatchTree)
1944 {
1945 PIRP Irp;
1946 PDEVICE_OBJECT DeviceObject;
1947 PFILE_OBJECT FileObject;
1948 PIO_STACK_LOCATION IoStack;
1949 KPROCESSOR_MODE PreviousMode;
1950 NTSTATUS Status = STATUS_SUCCESS;
1951
1952 DPRINT("NtNotifyChangeDirectoryFile()\n");
1953
1954 PAGED_CODE();
1955
1956 PreviousMode = ExGetPreviousMode();
1957
1958 if(PreviousMode != KernelMode)
1959 {
1960 _SEH_TRY
1961 {
1962 ProbeForWrite(IoStatusBlock,
1963 sizeof(IO_STATUS_BLOCK),
1964 sizeof(ULONG));
1965 if(BufferSize != 0)
1966 {
1967 ProbeForWrite(Buffer,
1968 BufferSize,
1969 sizeof(ULONG));
1970 }
1971 }
1972 _SEH_HANDLE
1973 {
1974 Status = _SEH_GetExceptionCode();
1975 }
1976 _SEH_END;
1977
1978 if(!NT_SUCCESS(Status))
1979 {
1980 return Status;
1981 }
1982 }
1983
1984 Status = ObReferenceObjectByHandle(FileHandle,
1985 FILE_LIST_DIRECTORY,
1986 IoFileObjectType,
1987 PreviousMode,
1988 (PVOID *)&FileObject,
1989 NULL);
1990 if (Status != STATUS_SUCCESS) return(Status);
1991
1992
1993 DeviceObject = FileObject->DeviceObject;
1994
1995
1996 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
1997 if (Irp==NULL)
1998 {
1999 ObDereferenceObject(FileObject);
2000 return STATUS_UNSUCCESSFUL;
2001 }
2002
2003 if (Event == NULL)
2004 {
2005 Event = &FileObject->Event;
2006 }
2007
2008 /* Trigger FileObject/Event dereferencing */
2009 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2010 Irp->RequestorMode = PreviousMode;
2011 Irp->UserIosb = IoStatusBlock;
2012 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2013 Irp->UserEvent = Event;
2014 KeResetEvent( Event );
2015 Irp->UserBuffer = Buffer;
2016 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
2017 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
2018
2019 IoStack = IoGetNextIrpStackLocation(Irp);
2020
2021 IoStack->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
2022 IoStack->MinorFunction = IRP_MN_NOTIFY_CHANGE_DIRECTORY;
2023 IoStack->Flags = 0;
2024 IoStack->Control = 0;
2025 IoStack->DeviceObject = DeviceObject;
2026 IoStack->FileObject = FileObject;
2027
2028 if (WatchTree)
2029 {
2030 IoStack->Flags = SL_WATCH_TREE;
2031 }
2032
2033 IoStack->Parameters.NotifyDirectory.CompletionFilter = CompletionFilter;
2034 IoStack->Parameters.NotifyDirectory.Length = BufferSize;
2035
2036 Status = IoCallDriver(FileObject->DeviceObject,Irp);
2037
2038 /* FIXME: Should we wait here or not for synchronously opened files? */
2039
2040 return Status;
2041 }
2042
2043 /*
2044 * @unimplemented
2045 */
2046 NTSTATUS
2047 STDCALL
2048 NtLockFile(IN HANDLE FileHandle,
2049 IN HANDLE EventHandle OPTIONAL,
2050 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
2051 IN PVOID ApcContext OPTIONAL,
2052 OUT PIO_STATUS_BLOCK IoStatusBlock,
2053 IN PLARGE_INTEGER ByteOffset,
2054 IN PLARGE_INTEGER Length,
2055 IN ULONG Key,
2056 IN BOOLEAN FailImmediately,
2057 IN BOOLEAN ExclusiveLock)
2058 {
2059 PFILE_OBJECT FileObject = NULL;
2060 PLARGE_INTEGER LocalLength = NULL;
2061 PIRP Irp = NULL;
2062 PIO_STACK_LOCATION StackPtr;
2063 PDEVICE_OBJECT DeviceObject;
2064 PKEVENT Event = NULL;
2065 BOOLEAN LocalEvent = FALSE;
2066 KPROCESSOR_MODE PreviousMode;
2067 LARGE_INTEGER CapturedByteOffset, CapturedLength;
2068 NTSTATUS Status = STATUS_SUCCESS;
2069 OBJECT_HANDLE_INFORMATION HandleInformation;
2070
2071 PAGED_CODE();
2072
2073 PreviousMode = KeGetPreviousMode();
2074
2075 CapturedByteOffset.QuadPart = 0;
2076 CapturedLength.QuadPart = 0;
2077
2078 /* Get File Object */
2079 Status = ObReferenceObjectByHandle(FileHandle,
2080 0,
2081 IoFileObjectType,
2082 PreviousMode,
2083 (PVOID*)&FileObject,
2084 &HandleInformation);
2085 if (!NT_SUCCESS(Status)) return Status;
2086
2087 if (PreviousMode != KernelMode)
2088 {
2089 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access unless
2090 we're in KernelMode! */
2091 if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_READ_DATA)))
2092 {
2093 DPRINT1("Invalid access rights\n");
2094 ObDereferenceObject(FileObject);
2095 return STATUS_ACCESS_DENIED;
2096 }
2097
2098 _SEH_TRY
2099 {
2100 ProbeForWrite(IoStatusBlock,
2101 sizeof(IO_STATUS_BLOCK),
2102 sizeof(ULONG));
2103 CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
2104 CapturedLength = ProbeForReadLargeInteger(Length);
2105 }
2106 _SEH_HANDLE
2107 {
2108 Status = _SEH_GetExceptionCode();
2109 }
2110 _SEH_END;
2111
2112 if (!NT_SUCCESS(Status))
2113 {
2114 ObDereferenceObject(FileObject);
2115 return Status;
2116 }
2117 }
2118 else
2119 {
2120 CapturedByteOffset = *ByteOffset;
2121 CapturedLength = *Length;
2122 }
2123
2124 /* Get Event Object */
2125 if (EventHandle)
2126 {
2127 Status = ObReferenceObjectByHandle(EventHandle,
2128 EVENT_MODIFY_STATE,
2129 ExEventObjectType,
2130 PreviousMode,
2131 (PVOID *)&Event,
2132 NULL);
2133 if (Status != STATUS_SUCCESS) return(Status);
2134 KeClearEvent(Event);
2135 }
2136
2137 /* Check if this is a direct open or not */
2138 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
2139 {
2140 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
2141 }
2142 else
2143 {
2144 DeviceObject = IoGetRelatedDeviceObject(FileObject);
2145 }
2146
2147 /* Check if we should use Sync IO or not */
2148 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
2149 {
2150 /* Use File Object event */
2151 KeClearEvent(&FileObject->Event);
2152 }
2153 else
2154 {
2155 LocalEvent = TRUE;
2156 }
2157
2158 /* Allocate the IRP */
2159 if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
2160 {
2161 ObDereferenceObject(FileObject);
2162 return STATUS_INSUFFICIENT_RESOURCES;
2163 }
2164
2165 /* Allocate local buffer */
2166 LocalLength = ExAllocatePoolWithTag(NonPagedPool,
2167 sizeof(LARGE_INTEGER),
2168 TAG_LOCK);
2169 if (!LocalLength)
2170 {
2171 IoFreeIrp(Irp);
2172 ObDereferenceObject(FileObject);
2173 return STATUS_INSUFFICIENT_RESOURCES;
2174 }
2175 *LocalLength = CapturedLength;
2176
2177 /* Set up the IRP */
2178 Irp->RequestorMode = PreviousMode;
2179 Irp->UserIosb = IoStatusBlock;
2180 Irp->UserEvent = Event;
2181 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2182 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2183
2184 /* Set up Stack Data */
2185 StackPtr = IoGetNextIrpStackLocation(Irp);
2186 StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
2187 StackPtr->MinorFunction = IRP_MN_LOCK;
2188 StackPtr->FileObject = FileObject;
2189
2190 /* Set Parameters */
2191 StackPtr->Parameters.LockControl.Length = LocalLength;
2192 StackPtr->Parameters.LockControl.ByteOffset = CapturedByteOffset;
2193 StackPtr->Parameters.LockControl.Key = Key;
2194
2195 /* Set Flags */
2196 if (FailImmediately) StackPtr->Flags = SL_FAIL_IMMEDIATELY;
2197 if (ExclusiveLock) StackPtr->Flags |= SL_EXCLUSIVE_LOCK;
2198
2199 /* Call the Driver */
2200 FileObject->LockOperation = TRUE;
2201 Status = IoCallDriver(DeviceObject, Irp);
2202 if (Status == STATUS_PENDING)
2203 {
2204 if (!LocalEvent)
2205 {
2206 KeWaitForSingleObject(&FileObject->Event,
2207 Executive,
2208 PreviousMode,
2209 FileObject->Flags & FO_ALERTABLE_IO,
2210 NULL);
2211 Status = FileObject->FinalStatus;
2212 }
2213 }
2214
2215 /* Return the Status */
2216 return Status;
2217 }
2218
2219 /*
2220 * NAME EXPORTED
2221 * NtOpenFile@24
2222 *
2223 * DESCRIPTION
2224 * Opens an existing file (simpler than NtCreateFile).
2225 *
2226 * ARGUMENTS
2227 * FileHandle (OUT)
2228 * Variable that receives the file handle on return;
2229 *
2230 * DesiredAccess
2231 * Access desired by the caller to the file;
2232 *
2233 * ObjectAttributes
2234 * Structue describing the file to be opened;
2235 *
2236 * IoStatusBlock (OUT)
2237 * Receives details about the result of the
2238 * operation;
2239 *
2240 * ShareAccess
2241 * Type of shared access the caller requires;
2242 *
2243 * OpenOptions
2244 * Options for the file open.
2245 *
2246 * RETURN VALUE
2247 * Status.
2248 *
2249 * NOTE
2250 * Undocumented.
2251 *
2252 * @implemented
2253 */
2254 NTSTATUS
2255 STDCALL
2256 NtOpenFile(PHANDLE FileHandle,
2257 ACCESS_MASK DesiredAccess,
2258 POBJECT_ATTRIBUTES ObjectAttributes,
2259 PIO_STATUS_BLOCK IoStatusBlock,
2260 ULONG ShareAccess,
2261 ULONG OpenOptions)
2262 {
2263 /* Call the I/O Function */
2264 return IoCreateFile(FileHandle,
2265 DesiredAccess,
2266 ObjectAttributes,
2267 IoStatusBlock,
2268 NULL,
2269 0,
2270 ShareAccess,
2271 FILE_OPEN,
2272 OpenOptions,
2273 NULL,
2274 0,
2275 CreateFileTypeNone,
2276 NULL,
2277 0);
2278 }
2279
2280 NTSTATUS
2281 IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
2282 IN FILE_INFORMATION_CLASS FileInformationClass,
2283 OUT PVOID FileInformation)
2284 {
2285 IO_STATUS_BLOCK IoStatusBlock;
2286 HANDLE FileHandle;
2287 NTSTATUS Status;
2288 KPROCESSOR_MODE AccessMode;
2289 UNICODE_STRING ObjectName;
2290 OBJECT_CREATE_INFORMATION ObjectCreateInfo;
2291 OBJECT_ATTRIBUTES LocalObjectAttributes;
2292 ULONG BufferSize;
2293 union
2294 {
2295 FILE_BASIC_INFORMATION BasicInformation;
2296 FILE_NETWORK_OPEN_INFORMATION NetworkOpenInformation;
2297 }LocalFileInformation;
2298
2299 if (FileInformationClass == FileBasicInformation)
2300 {
2301 BufferSize = sizeof(FILE_BASIC_INFORMATION);
2302 }
2303 else if (FileInformationClass == FileNetworkOpenInformation)
2304 {
2305 BufferSize = sizeof(FILE_NETWORK_OPEN_INFORMATION);
2306 }
2307 else
2308 {
2309 return STATUS_INVALID_PARAMETER;
2310 }
2311
2312 AccessMode = ExGetPreviousMode();
2313
2314 if (AccessMode != KernelMode)
2315 {
2316 Status = STATUS_SUCCESS;
2317 _SEH_TRY
2318 {
2319 ProbeForWrite(FileInformation,
2320 BufferSize,
2321 sizeof(ULONG));
2322 }
2323 _SEH_HANDLE
2324 {
2325 Status = _SEH_GetExceptionCode();
2326 }
2327 _SEH_END;
2328 if (NT_SUCCESS(Status))
2329 {
2330 Status = ObpCaptureObjectAttributes(ObjectAttributes,
2331 AccessMode,
2332 NULL,
2333 &ObjectCreateInfo,
2334 &ObjectName);
2335 }
2336 if (!NT_SUCCESS(Status))
2337 {
2338 return Status;
2339 }
2340 InitializeObjectAttributes(&LocalObjectAttributes,
2341 &ObjectName,
2342 ObjectCreateInfo.Attributes,
2343 ObjectCreateInfo.RootDirectory,
2344 ObjectCreateInfo.SecurityDescriptor);
2345 }
2346
2347 /* Open the file */
2348 Status = ZwOpenFile(&FileHandle,
2349 SYNCHRONIZE | FILE_READ_ATTRIBUTES,
2350 AccessMode == KernelMode ? ObjectAttributes : &LocalObjectAttributes,
2351 &IoStatusBlock,
2352 0,
2353 FILE_SYNCHRONOUS_IO_NONALERT);
2354 if (AccessMode != KernelMode)
2355 {
2356 ObpReleaseCapturedAttributes(&ObjectCreateInfo);
2357 ExFreePool(ObjectName.Buffer);
2358 }
2359 if (!NT_SUCCESS (Status))
2360 {
2361 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status);
2362 return Status;
2363 }
2364
2365 /* Get file attributes */
2366 Status = ZwQueryInformationFile(FileHandle,
2367 &IoStatusBlock,
2368 AccessMode == KernelMode ? FileInformation : &LocalFileInformation,
2369 BufferSize,
2370 FileInformationClass);
2371 if (!NT_SUCCESS (Status))
2372 {
2373 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status);
2374 }
2375 ZwClose(FileHandle);
2376
2377 if (NT_SUCCESS(Status) && AccessMode != KernelMode)
2378 {
2379 _SEH_TRY
2380 {
2381 memcpy(FileInformation, &LocalFileInformation, BufferSize);
2382 }
2383 _SEH_HANDLE
2384 {
2385 Status = _SEH_GetExceptionCode();
2386 }
2387 _SEH_END;
2388 }
2389 return Status;
2390 }
2391
2392 NTSTATUS
2393 STDCALL
2394 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
2395 OUT PFILE_BASIC_INFORMATION FileInformation)
2396 {
2397 return IopQueryAttributesFile(ObjectAttributes,
2398 FileBasicInformation,
2399 FileInformation);
2400 }
2401
2402
2403 /*
2404 * @implemented
2405 *
2406 * FUNCTION: Queries a directory file.
2407 * ARGUMENTS:
2408 * FileHandle = Handle to a directory file
2409 * EventHandle = Handle to the event signaled on completion
2410 * ApcRoutine = Asynchroneous procedure callback, called on completion
2411 * ApcContext = Argument to the apc.
2412 * IoStatusBlock = Caller supplies storage for extended status information.
2413 * FileInformation = Caller supplies storage for the resulting information.
2414 *
2415 * FileNameInformation FILE_NAMES_INFORMATION
2416 * FileDirectoryInformation FILE_DIRECTORY_INFORMATION
2417 * FileFullDirectoryInformation FILE_FULL_DIRECTORY_INFORMATION
2418 * FileBothDirectoryInformation FILE_BOTH_DIR_INFORMATION
2419 *
2420 * Length = Size of the storage supplied
2421 * FileInformationClass = Indicates the type of information requested.
2422 * ReturnSingleEntry = Specify true if caller only requests the first
2423 * directory found.
2424 * FileName = Initial directory name to query, that may contain wild
2425 * cards.
2426 * RestartScan = Number of times the action should be repeated
2427 * RETURNS: Status [ STATUS_SUCCESS, STATUS_ACCESS_DENIED, STATUS_INSUFFICIENT_RESOURCES,
2428 * STATUS_INVALID_PARAMETER, STATUS_INVALID_DEVICE_REQUEST, STATUS_BUFFER_OVERFLOW,
2429 * STATUS_INVALID_INFO_CLASS, STATUS_NO_SUCH_FILE, STATUS_NO_MORE_FILES ]
2430 */
2431 NTSTATUS
2432 STDCALL
2433 NtQueryDirectoryFile(IN HANDLE FileHandle,
2434 IN HANDLE PEvent OPTIONAL,
2435 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
2436 IN PVOID ApcContext OPTIONAL,
2437 OUT PIO_STATUS_BLOCK IoStatusBlock,
2438 OUT PVOID FileInformation,
2439 IN ULONG Length,
2440 IN FILE_INFORMATION_CLASS FileInformationClass,
2441 IN BOOLEAN ReturnSingleEntry,
2442 IN PUNICODE_STRING FileName OPTIONAL,
2443 IN BOOLEAN RestartScan)
2444 {
2445 PIRP Irp;
2446 PDEVICE_OBJECT DeviceObject;
2447 PFILE_OBJECT FileObject;
2448 PIO_STACK_LOCATION StackPtr;
2449 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
2450 NTSTATUS Status = STATUS_SUCCESS;
2451 BOOLEAN LocalEvent = FALSE;
2452 PKEVENT Event = NULL;
2453
2454 DPRINT("NtQueryDirectoryFile()\n");
2455 PAGED_CODE();
2456
2457 /* Validate User-Mode Buffers */
2458 if(PreviousMode != KernelMode)
2459 {
2460 _SEH_TRY
2461 {
2462 ProbeForWrite(IoStatusBlock,
2463 sizeof(IO_STATUS_BLOCK),
2464 sizeof(ULONG));
2465 ProbeForWrite(FileInformation,
2466 Length,
2467 sizeof(ULONG));
2468 }
2469 _SEH_HANDLE
2470 {
2471 Status = _SEH_GetExceptionCode();
2472 }
2473 _SEH_END;
2474
2475 if(!NT_SUCCESS(Status)) return Status;
2476 }
2477
2478 /* Get File Object */
2479 Status = ObReferenceObjectByHandle(FileHandle,
2480 FILE_LIST_DIRECTORY,
2481 IoFileObjectType,
2482 PreviousMode,
2483 (PVOID *)&FileObject,
2484 NULL);
2485 if (Status != STATUS_SUCCESS) return(Status);
2486
2487 /* Get Event Object */
2488 if (PEvent)
2489 {
2490 Status = ObReferenceObjectByHandle(PEvent,
2491 EVENT_MODIFY_STATE,
2492 ExEventObjectType,
2493 PreviousMode,
2494 (PVOID *)&Event,
2495 NULL);
2496 if (Status != STATUS_SUCCESS) return(Status);
2497 KeClearEvent(Event);
2498 }
2499
2500 /* Check if this is a direct open or not */
2501 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
2502 {
2503 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
2504 }
2505 else
2506 {
2507 DeviceObject = IoGetRelatedDeviceObject(FileObject);
2508 }
2509
2510 /* Check if we should use Sync IO or not */
2511 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
2512 {
2513 /* Use File Object event */
2514 KeClearEvent(&FileObject->Event);
2515 }
2516 else
2517 {
2518 LocalEvent = TRUE;
2519 }
2520
2521 /* Allocate the IRP */
2522 if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
2523 {
2524 ObDereferenceObject(FileObject);
2525 return STATUS_INSUFFICIENT_RESOURCES;
2526 }
2527
2528 /* Set up the IRP */
2529 Irp->RequestorMode = PreviousMode;
2530 Irp->UserIosb = IoStatusBlock;
2531 Irp->UserEvent = Event;
2532 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2533 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2534 Irp->UserBuffer = FileInformation;
2535 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
2536 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
2537
2538 /* Set up Stack Data */
2539 StackPtr = IoGetNextIrpStackLocation(Irp);
2540 StackPtr->FileObject = FileObject;
2541 StackPtr->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
2542 StackPtr->MinorFunction = IRP_MN_QUERY_DIRECTORY;
2543
2544 /* Set Parameters */
2545 StackPtr->Parameters.QueryDirectory.FileInformationClass = FileInformationClass;
2546 StackPtr->Parameters.QueryDirectory.FileName = FileName;
2547 StackPtr->Parameters.QueryDirectory.FileIndex = 0;
2548 StackPtr->Parameters.QueryDirectory.Length = Length;
2549 StackPtr->Flags = 0;
2550 if (RestartScan) StackPtr->Flags = SL_RESTART_SCAN;
2551 if (ReturnSingleEntry) StackPtr->Flags |= SL_RETURN_SINGLE_ENTRY;
2552
2553 /* Call the Driver */
2554 Status = IoCallDriver(DeviceObject, Irp);
2555 if (Status == STATUS_PENDING)
2556 {
2557 if (!LocalEvent)
2558 {
2559 KeWaitForSingleObject(&FileObject->Event,
2560 Executive,
2561 PreviousMode,
2562 FileObject->Flags & FO_ALERTABLE_IO,
2563 NULL);
2564 Status = FileObject->FinalStatus;
2565 }
2566 }
2567
2568 /* Return the Status */
2569 return Status;
2570 }
2571
2572 /*
2573 * @unimplemented
2574 */
2575 NTSTATUS STDCALL
2576 NtQueryEaFile(IN HANDLE FileHandle,
2577 OUT PIO_STATUS_BLOCK IoStatusBlock,
2578 OUT PVOID Buffer,
2579 IN ULONG Length,
2580 IN BOOLEAN ReturnSingleEntry,
2581 IN PVOID EaList OPTIONAL,
2582 IN ULONG EaListLength,
2583 IN PULONG EaIndex OPTIONAL,
2584 IN BOOLEAN RestartScan)
2585 {
2586 UNIMPLEMENTED;
2587 return STATUS_NOT_IMPLEMENTED;
2588 }
2589
2590 NTSTATUS
2591 STDCALL
2592 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
2593 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation)
2594 {
2595 return IopQueryAttributesFile(ObjectAttributes,
2596 FileNetworkOpenInformation,
2597 FileInformation);
2598 }
2599
2600 /*
2601 * @implemented
2602 */
2603 NTSTATUS STDCALL
2604 NtQueryInformationFile(HANDLE FileHandle,
2605 PIO_STATUS_BLOCK IoStatusBlock,
2606 PVOID FileInformation,
2607 ULONG Length,
2608 FILE_INFORMATION_CLASS FileInformationClass)
2609 {
2610 OBJECT_HANDLE_INFORMATION HandleInformation;
2611 PFILE_OBJECT FileObject;
2612 NTSTATUS Status;
2613 PIRP Irp;
2614 PDEVICE_OBJECT DeviceObject;
2615 PIO_STACK_LOCATION StackPtr;
2616 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
2617 KEVENT Event;
2618 BOOLEAN LocalEvent = FALSE;
2619 BOOLEAN Failed = FALSE;
2620
2621 ASSERT(IoStatusBlock != NULL);
2622 ASSERT(FileInformation != NULL);
2623
2624 DPRINT("NtQueryInformationFile(Handle 0x%p StatBlk 0x%p FileInfo 0x%p Length %d "
2625 "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
2626 Length, FileInformationClass);
2627
2628 /* Reference the Handle */
2629 Status = ObReferenceObjectByHandle(FileHandle,
2630 0,
2631 IoFileObjectType,
2632 PreviousMode,
2633 (PVOID *)&FileObject,
2634 &HandleInformation);
2635 if (!NT_SUCCESS(Status)) return Status;
2636
2637 /* Check information class specific access rights */
2638 switch (FileInformationClass)
2639 {
2640 case FileBasicInformation:
2641 if (!(HandleInformation.GrantedAccess & FILE_READ_ATTRIBUTES))
2642 Failed = TRUE;
2643 break;
2644
2645 case FilePositionInformation:
2646 if (!(HandleInformation.GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA)) ||
2647 !(FileObject->Flags & FO_SYNCHRONOUS_IO))
2648 Failed = TRUE;
2649 break;
2650
2651 default:
2652 break;
2653 }
2654
2655 if (Failed)
2656 {
2657 DPRINT1("NtQueryInformationFile() returns STATUS_ACCESS_DENIED!\n");
2658 ObDereferenceObject(FileObject);
2659 return STATUS_ACCESS_DENIED;
2660 }
2661
2662 if (FileInformationClass == FilePositionInformation)
2663 {
2664 if (Length < sizeof(FILE_POSITION_INFORMATION))
2665 {
2666 Status = STATUS_BUFFER_OVERFLOW;
2667 }
2668 else
2669 {
2670 _SEH_TRY
2671 {
2672 ((PFILE_POSITION_INFORMATION)FileInformation)->CurrentByteOffset = FileObject->CurrentByteOffset;
2673 IoStatusBlock->Information = sizeof(FILE_POSITION_INFORMATION);
2674 Status = IoStatusBlock->Status = STATUS_SUCCESS;
2675 }
2676 _SEH_HANDLE
2677 {
2678 Status = _SEH_GetExceptionCode();
2679 }
2680 _SEH_END;
2681 }
2682 ObDereferenceObject(FileObject);
2683 return Status;
2684 }
2685
2686 DPRINT("FileObject 0x%p\n", FileObject);
2687
2688 /* Check if this is a direct open or not */
2689 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
2690 {
2691 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
2692 }
2693 else
2694 {
2695 DeviceObject = IoGetRelatedDeviceObject(FileObject);
2696 }
2697
2698 if (FileInformationClass == FileAlignmentInformation)
2699 {
2700 if (Length < sizeof(FILE_ALIGNMENT_INFORMATION))
2701 {
2702 Status = STATUS_BUFFER_OVERFLOW;
2703 }
2704 else
2705 {
2706 _SEH_TRY
2707 {
2708 ((PFILE_ALIGNMENT_INFORMATION)FileInformation)->AlignmentRequirement = DeviceObject->AlignmentRequirement;
2709 IoStatusBlock->Information = sizeof(FILE_ALIGNMENT_INFORMATION);
2710 Status = IoStatusBlock->Status = STATUS_SUCCESS;
2711 }
2712 _SEH_HANDLE
2713 {
2714 Status = _SEH_GetExceptionCode();
2715 }
2716 _SEH_END;
2717 }
2718 ObDereferenceObject(FileObject);
2719 return Status;
2720 }
2721
2722 /* Check if we should use Sync IO or not */
2723 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
2724 {
2725 /* Use File Object event */
2726 KeClearEvent(&FileObject->Event);
2727 }
2728 else
2729 {
2730 /* Use local event */
2731 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
2732 LocalEvent = TRUE;
2733 }
2734
2735 /* Allocate the IRP */
2736 if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
2737 {
2738 ObDereferenceObject(FileObject);
2739 return STATUS_INSUFFICIENT_RESOURCES;
2740 }
2741
2742 /* Allocate the System Buffer */
2743 if (!(Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
2744 Length,
2745 TAG_SYSB)))
2746 {
2747 IoFreeIrp(Irp);
2748 ObDereferenceObject(FileObject);
2749 return STATUS_INSUFFICIENT_RESOURCES;
2750 }
2751
2752 /* Set up the IRP */
2753 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2754 Irp->RequestorMode = PreviousMode;
2755 Irp->UserIosb = IoStatusBlock;
2756 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
2757 Irp->UserBuffer = FileInformation;
2758 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2759 Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER | IRP_INPUT_OPERATION;
2760 Irp->Flags |= (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
2761
2762 /* Set up Stack Data */
2763 StackPtr = IoGetNextIrpStackLocation(Irp);
2764 StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
2765 StackPtr->FileObject = FileObject;
2766
2767 /* Set the Parameters */
2768 StackPtr->Parameters.QueryFile.FileInformationClass = FileInformationClass;
2769 StackPtr->Parameters.QueryFile.Length = Length;
2770
2771 /* Call the Driver */
2772 Status = IoCallDriver(DeviceObject, Irp);
2773 if (Status == STATUS_PENDING)
2774 {
2775 if (LocalEvent)
2776 {
2777 KeWaitForSingleObject(&Event,
2778 Executive,
2779 PreviousMode,
2780 FileObject->Flags & FO_ALERTABLE_IO,
2781 NULL);
2782 Status = IoStatusBlock->Status;
2783 }
2784 else
2785 {
2786 KeWaitForSingleObject(&FileObject->Event,
2787 Executive,
2788 PreviousMode,
2789 FileObject->Flags & FO_ALERTABLE_IO,
2790 NULL);
2791 Status = FileObject->FinalStatus;
2792 }
2793 }
2794
2795 /* Return the Status */
2796 return Status;
2797 }
2798
2799 /*
2800 * @unimplemented
2801 */
2802 NTSTATUS
2803 STDCALL
2804 NtQueryQuotaInformationFile(IN HANDLE FileHandle,
2805 OUT PIO_STATUS_BLOCK IoStatusBlock,
2806 OUT PVOID Buffer,
2807 IN ULONG Length,
2808 IN BOOLEAN ReturnSingleEntry,
2809 IN PVOID SidList OPTIONAL,
2810 IN ULONG SidListLength,
2811 IN PSID StartSid OPTIONAL,
2812 IN BOOLEAN RestartScan)
2813 {
2814 UNIMPLEMENTED;
2815 return STATUS_NOT_IMPLEMENTED;
2816 }
2817
2818 /*
2819 * NAME EXPORTED
2820 * NtReadFile
2821 *
2822 * DESCRIPTION
2823 *
2824 * ARGUMENTS
2825 *
2826 * RETURN VALUE
2827 *
2828 * REVISIONS
2829 *
2830 * @implemented
2831 */
2832 NTSTATUS
2833 STDCALL
2834 NtReadFile(IN HANDLE FileHandle,
2835 IN HANDLE Event OPTIONAL,
2836 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
2837 IN PVOID ApcContext OPTIONAL,
2838 OUT PIO_STATUS_BLOCK IoStatusBlock,
2839 OUT PVOID Buffer,
2840 IN ULONG Length,
2841 IN PLARGE_INTEGER ByteOffset OPTIONAL,
2842 IN PULONG Key OPTIONAL)
2843 {
2844 NTSTATUS Status = STATUS_SUCCESS;
2845 PFILE_OBJECT FileObject;
2846 PIRP Irp = NULL;
2847 PDEVICE_OBJECT DeviceObject;
2848 PIO_STACK_LOCATION StackPtr;
2849 KPROCESSOR_MODE PreviousMode;
2850 BOOLEAN LocalEvent = FALSE;
2851 PKEVENT EventObject = NULL;
2852 LARGE_INTEGER CapturedByteOffset;
2853
2854 DPRINT("NtReadFile(FileHandle 0x%p Buffer 0x%p Length %x ByteOffset 0x%p, "
2855 "IoStatusBlock 0x%p)\n", FileHandle, Buffer, Length, ByteOffset,
2856 IoStatusBlock);
2857
2858 PAGED_CODE();
2859
2860 PreviousMode = KeGetPreviousMode();
2861 CapturedByteOffset.QuadPart = 0;
2862
2863 /* Validate User-Mode Buffers */
2864 if(PreviousMode != KernelMode)
2865 {
2866 _SEH_TRY
2867 {
2868 ProbeForWrite(IoStatusBlock,
2869 sizeof(IO_STATUS_BLOCK),
2870 sizeof(ULONG));
2871 ProbeForWrite(Buffer,
2872 Length,
2873 1);
2874 if (ByteOffset != NULL)
2875 {
2876 CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
2877 }
2878 /* FIXME - probe other pointers and capture information */
2879 }
2880 _SEH_HANDLE
2881 {
2882 Status = _SEH_GetExceptionCode();
2883 }
2884 _SEH_END;
2885
2886 if(!NT_SUCCESS(Status)) return Status;
2887 }
2888 else
2889 {
2890 if (ByteOffset != NULL)
2891 {
2892 CapturedByteOffset = *ByteOffset;
2893 }
2894 }
2895
2896 /* Get File Object */
2897 Status = ObReferenceObjectByHandle(FileHandle,
2898 FILE_READ_DATA,
2899 IoFileObjectType,
2900 PreviousMode,
2901 (PVOID*)&FileObject,
2902 NULL);
2903 if (!NT_SUCCESS(Status)) return Status;
2904
2905 /* Check the Byte Offset */
2906 if (ByteOffset == NULL ||
2907 (CapturedByteOffset.u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
2908 CapturedByteOffset.u.HighPart == -1))
2909 {
2910 /* a valid ByteOffset is required if asynch. op. */
2911 if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
2912 {
2913 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
2914 ObDereferenceObject(FileObject);
2915 return STATUS_INVALID_PARAMETER;
2916 }
2917
2918 /* Use the Current Byte OFfset */
2919 CapturedByteOffset = FileObject->CurrentByteOffset;
2920 }
2921
2922 /* Check for event */
2923 if (Event)
2924 {
2925 /* Reference it */
2926 Status = ObReferenceObjectByHandle(Event,
2927 EVENT_MODIFY_STATE,
2928 ExEventObjectType,
2929 PreviousMode,
2930 (PVOID*)&EventObject,
2931 NULL);
2932 if (!NT_SUCCESS(Status))
2933 {
2934 ObDereferenceObject(FileObject);
2935 return Status;
2936 }
2937 KeClearEvent(EventObject);
2938 }
2939
2940 /* Check if this is a direct open or not */
2941 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
2942 {
2943 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
2944 }
2945 else
2946 {
2947 DeviceObject = IoGetRelatedDeviceObject(FileObject);
2948 }
2949
2950 /* Check if we should use Sync IO or not */
2951 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
2952 {
2953 /* Use File Object event */
2954 KeClearEvent(&FileObject->Event);
2955 }
2956 else
2957 {
2958 LocalEvent = TRUE;
2959 }
2960
2961 /* Create the IRP */
2962 _SEH_TRY
2963 {
2964 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
2965 DeviceObject,
2966 Buffer,
2967 Length,
2968 &CapturedByteOffset,
2969 EventObject,
2970 IoStatusBlock);
2971 if (Irp == NULL)
2972 {
2973 Status = STATUS_INSUFFICIENT_RESOURCES;
2974 }
2975 }
2976 _SEH_HANDLE
2977 {
2978 Status = _SEH_GetExceptionCode();
2979 }
2980 _SEH_END;
2981
2982 /* Cleanup if IRP Allocation Failed */
2983 if (!NT_SUCCESS(Status))
2984 {
2985 if (Event) ObDereferenceObject(EventObject);
2986 ObDereferenceObject(FileObject);
2987 return Status;
2988 }
2989
2990 /* Set up IRP Data */
2991 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2992 Irp->RequestorMode = PreviousMode;
2993 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
2994 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
2995 Irp->Flags |= IRP_READ_OPERATION;
2996 #if 0
2997 /* FIXME:
2998 * Vfat doesn't handle non cached files correctly.
2999 */
3000 if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) Irp->Flags |= IRP_NOCACHE;
3001 #endif
3002
3003 /* Setup Stack Data */
3004 StackPtr = IoGetNextIrpStackLocation(Irp);
3005 StackPtr->FileObject = FileObject;
3006 StackPtr->Parameters.Read.Key = Key ? *Key : 0;
3007
3008 /* Call the Driver */
3009 Status = IoCallDriver(DeviceObject, Irp);
3010 if (Status == STATUS_PENDING)
3011 {
3012 if (!LocalEvent)
3013 {
3014 KeWaitForSingleObject(&FileObject->Event,
3015 Executive,
3016 PreviousMode,
3017 FileObject->Flags & FO_ALERTABLE_IO,
3018 NULL);
3019 Status = FileObject->FinalStatus;
3020 }
3021 }
3022
3023 /* Return the Status */
3024 return Status;
3025 }
3026
3027 /*
3028 * NAME EXPORTED
3029 * NtReadFileScatter
3030 *
3031 * DESCRIPTION
3032 *
3033 * ARGUMENTS
3034 *
3035 * RETURN VALUE
3036 *
3037 * REVISIONS
3038 */
3039 NTSTATUS
3040 STDCALL
3041 NtReadFileScatter(IN HANDLE FileHandle,
3042 IN HANDLE Event OPTIONAL,
3043 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
3044 IN PVOID UserApcContext OPTIONAL,
3045 OUT PIO_STATUS_BLOCK UserIoStatusBlock,
3046 IN FILE_SEGMENT_ELEMENT BufferDescription [],
3047 IN ULONG BufferLength,
3048 IN PLARGE_INTEGER ByteOffset,
3049 IN PULONG Key OPTIONAL)
3050 {
3051 UNIMPLEMENTED;
3052 return(STATUS_NOT_IMPLEMENTED);
3053 }
3054
3055 /*
3056 * @unimplemented
3057 */
3058 NTSTATUS
3059 STDCALL
3060 NtSetEaFile(IN HANDLE FileHandle,
3061 IN PIO_STATUS_BLOCK IoStatusBlock,
3062 IN PVOID EaBuffer,
3063 IN ULONG EaBufferSize)
3064 {
3065 UNIMPLEMENTED;
3066 return STATUS_NOT_IMPLEMENTED;
3067 }
3068
3069 /*
3070 * @implemented
3071 */
3072 NTSTATUS STDCALL
3073 NtSetInformationFile(HANDLE FileHandle,
3074 PIO_STATUS_BLOCK IoStatusBlock,
3075 PVOID FileInformation,
3076 ULONG Length,
3077 FILE_INFORMATION_CLASS FileInformationClass)
3078 {
3079 OBJECT_HANDLE_INFORMATION HandleInformation;
3080 PIO_STACK_LOCATION StackPtr;
3081 PFILE_OBJECT FileObject;
3082 PDEVICE_OBJECT DeviceObject;
3083 PIRP Irp;
3084 KEVENT Event;
3085 BOOLEAN LocalEvent = FALSE;
3086 NTSTATUS Status = STATUS_SUCCESS;
3087 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
3088 BOOLEAN Failed = FALSE;
3089
3090 DPRINT("NtSetInformationFile(Handle 0x%p StatBlk 0x%p FileInfo 0x%p Length %d "
3091 "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
3092 Length, FileInformationClass);
3093
3094 if (PreviousMode != KernelMode)
3095 {
3096 _SEH_TRY
3097 {
3098 if (IoStatusBlock != NULL)
3099 {
3100 ProbeForWrite(IoStatusBlock,
3101 sizeof(IO_STATUS_BLOCK),
3102 sizeof(ULONG));
3103 }
3104
3105 if (Length != 0)
3106 {
3107 ProbeForRead(FileInformation,
3108 Length,
3109 1);
3110 }
3111 }
3112 _SEH_HANDLE
3113 {
3114 Status = _SEH_GetExceptionCode();
3115 }
3116 _SEH_END;
3117
3118 if (!NT_SUCCESS(Status))
3119 {
3120 return Status;
3121 }
3122 }
3123 else
3124 {
3125 ASSERT(IoStatusBlock != NULL);
3126 ASSERT(FileInformation != NULL);
3127 }
3128
3129 /* Get the file object from the file handle */
3130 Status = ObReferenceObjectByHandle(FileHandle,
3131 0,
3132 IoFileObjectType,
3133 PreviousMode,
3134 (PVOID *)&FileObject,
3135 &HandleInformation);
3136 if (!NT_SUCCESS(Status)) return Status;
3137
3138 /* Check information class specific access rights */
3139 switch (FileInformationClass)
3140 {
3141 case FileBasicInformation:
3142 if (!(HandleInformation.GrantedAccess & FILE_WRITE_ATTRIBUTES))
3143 Failed = TRUE;
3144 break;
3145
3146 case FileDispositionInformation:
3147 if (!(HandleInformation.GrantedAccess & DELETE))
3148 Failed = TRUE;
3149 break;
3150
3151 case FilePositionInformation:
3152 if (!(HandleInformation.GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA)) ||
3153 !(FileObject->Flags & FO_SYNCHRONOUS_IO))
3154 Failed = TRUE;
3155 break;
3156
3157 case FileEndOfFileInformation:
3158 if (!(HandleInformation.GrantedAccess & FILE_WRITE_DATA))
3159 Failed = TRUE;
3160 break;
3161
3162 default:
3163 break;
3164 }
3165
3166 if (Failed)
3167 {
3168 DPRINT1("NtSetInformationFile() returns STATUS_ACCESS_DENIED!\n");
3169 ObDereferenceObject(FileObject);
3170 return STATUS_ACCESS_DENIED;
3171 }
3172
3173 DPRINT("FileObject 0x%p\n", FileObject);
3174
3175 if (FileInformationClass == FilePositionInformation)
3176 {
3177 if (Length < sizeof(FILE_POSITION_INFORMATION))
3178 {
3179 Status = STATUS_BUFFER_OVERFLOW;
3180 }
3181 else
3182 {
3183 _SEH_TRY
3184 {
3185 FileObject->CurrentByteOffset = ((PFILE_POSITION_INFORMATION)FileInformation)->CurrentByteOffset;
3186 IoStatusBlock->Information = 0;
3187 Status = IoStatusBlock->Status = STATUS_SUCCESS;
3188 }
3189 _SEH_HANDLE
3190 {
3191 Status = _SEH_GetExceptionCode();
3192 }
3193 _SEH_END;
3194 }
3195 ObDereferenceObject(FileObject);
3196 return Status;
3197 }
3198
3199 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
3200 /* Handle IO Completion Port quickly */
3201 if (FileInformationClass == FileCompletionInformation)
3202 {
3203 PVOID Queue;
3204 PFILE_COMPLETION_INFORMATION CompletionInfo = FileInformation;
3205 PIO_COMPLETION_CONTEXT Context;
3206
3207 if (FileObject->Flags & FO_SYNCHRONOUS_IO || FileObject->CompletionContext != NULL)
3208 {
3209 Status = STATUS_INVALID_PARAMETER;
3210 }
3211 else
3212 {
3213 if (Length < sizeof(FILE_COMPLETION_INFORMATION))
3214 {
3215 Status = STATUS_INFO_LENGTH_MISMATCH;
3216 }
3217 else
3218 {
3219 /* Reference the Port */
3220 Status = ObReferenceObjectByHandle(CompletionInfo->Port, /* FIXME - protect with SEH! */
3221 IO_COMPLETION_MODIFY_STATE,
3222 IoCompletionType,
3223 PreviousMode,
3224 (PVOID*)&Queue,
3225 NULL);
3226 if (NT_SUCCESS(Status))
3227 {
3228 /* Allocate the Context */
3229 Context = ExAllocatePoolWithTag(PagedPool,
3230 sizeof(IO_COMPLETION_CONTEXT),
3231 TAG('I', 'o', 'C', 'p'));
3232
3233 if (Context != NULL)
3234 {
3235 /* Set the Data */
3236 Context->Key = CompletionInfo->Key; /* FIXME - protect with SEH! */
3237 Context->Port = Queue;
3238
3239 if (InterlockedCompareExchangePointer(&FileObject->CompletionContext,
3240 Context,
3241 NULL) != NULL)
3242 {
3243 /* someone else set the completion port in the
3244 meanwhile, fail */
3245 ExFreePool(Context);
3246 ObDereferenceObject(Queue);
3247 Status = STATUS_INVALID_PARAMETER;
3248 }
3249 }
3250 else
3251 {
3252 /* Dereference the Port now */
3253 ObDereferenceObject(Queue);
3254 Status = STATUS_INSUFFICIENT_RESOURCES;
3255 }
3256 }
3257 }
3258 }
3259
3260 /* Complete the I/O */
3261 ObDereferenceObject(FileObject);
3262 return Status;
3263 }
3264
3265 /* Check if this is a direct open or not */
3266 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
3267 {
3268 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
3269 }
3270 else
3271 {
3272 DeviceObject = IoGetRelatedDeviceObject(FileObject);
3273 }
3274
3275 /* Check if we should use Sync IO or not */
3276 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
3277 {
3278 /* Use File Object event */
3279 KeClearEvent(&FileObject->Event);
3280 }
3281 else
3282 {
3283 /* Use local event */
3284 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
3285 LocalEvent = TRUE;
3286 }
3287
3288 /* Allocate the IRP */
3289 if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
3290 {
3291 ObDereferenceObject(FileObject);
3292 return STATUS_INSUFFICIENT_RESOURCES;
3293 }
3294
3295 /* Allocate the System Buffer */
3296 if (!(Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
3297 Length,
3298 TAG_SYSB)))
3299 {
3300 Status = STATUS_INSUFFICIENT_RESOURCES;
3301 goto failfreeirp;
3302 }
3303
3304 /* Copy the data inside */
3305 if (PreviousMode != KernelMode)
3306 {
3307 _SEH_TRY
3308 {
3309 /* no need to probe again */
3310 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
3311 FileInformation,
3312 Length);
3313 }
3314 _SEH_HANDLE
3315 {
3316 Status = _SEH_GetExceptionCode();
3317 }
3318 _SEH_END;
3319
3320 if (!NT_SUCCESS(Status))
3321 {
3322 ExFreePoolWithTag(Irp->AssociatedIrp.SystemBuffer,
3323 TAG_SYSB);
3324 Irp->AssociatedIrp.SystemBuffer = NULL;
3325 failfreeirp:
3326 IoFreeIrp(Irp);
3327 ObDereferenceObject(FileObject);
3328 return Status;
3329 }
3330 }
3331 else
3332 {
3333 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
3334 FileInformation,
3335 Length);
3336 }
3337
3338 /* Set up the IRP */
3339 Irp->Tail.Overlay.OriginalFileObject = FileObject;
3340 Irp->RequestorMode = PreviousMode;
3341 Irp->UserIosb = IoStatusBlock;
3342 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
3343 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
3344 Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
3345 Irp->Flags |= (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
3346
3347 /* Set up Stack Data */
3348 StackPtr = IoGetNextIrpStackLocation(Irp);
3349 StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION;
3350 StackPtr->FileObject = FileObject;
3351
3352 /* Set the Parameters */
3353 StackPtr->Parameters.SetFile.FileInformationClass = FileInformationClass;
3354 StackPtr->Parameters.SetFile.Length = Length;
3355
3356 /* Call the Driver */
3357 Status = IoCallDriver(DeviceObject, Irp);
3358 if (Status == STATUS_PENDING)
3359 {
3360 if (LocalEvent)
3361 {
3362 KeWaitForSingleObject(&Event,
3363 Executive,
3364 PreviousMode,
3365 FileObject->Flags & FO_ALERTABLE_IO,
3366 NULL);
3367 _SEH_TRY
3368 {
3369 Status = IoStatusBlock->Status;
3370 }
3371 _SEH_HANDLE
3372 {
3373 Status = _SEH_GetExceptionCode();
3374 }
3375 _SEH_END;
3376 }
3377 else
3378 {
3379 KeWaitForSingleObject(&FileObject->Event,
3380 Executive,
3381 PreviousMode,
3382 FileObject->Flags & FO_ALERTABLE_IO,
3383 NULL);
3384 _SEH_TRY
3385 {
3386 Status = FileObject->FinalStatus;
3387 }
3388 _SEH_HANDLE
3389 {
3390 Status = _SEH_GetExceptionCode();
3391 }
3392 _SEH_END;
3393 }
3394 }
3395
3396 /* Return the Status */
3397 return Status;
3398 }
3399
3400 /*
3401 * @unimplemented
3402 */
3403 NTSTATUS
3404 STDCALL
3405 NtSetQuotaInformationFile(HANDLE FileHandle,
3406 PIO_STATUS_BLOCK IoStatusBlock,
3407 PVOID Buffer,
3408 ULONG BufferLength)
3409 {
3410 UNIMPLEMENTED;
3411 return STATUS_NOT_IMPLEMENTED;
3412 }
3413
3414 /*
3415 * @unimplemented
3416 */
3417 NTSTATUS
3418 STDCALL
3419 NtUnlockFile(IN HANDLE FileHandle,
3420 OUT PIO_STATUS_BLOCK IoStatusBlock,
3421 IN PLARGE_INTEGER ByteOffset,
3422 IN PLARGE_INTEGER Length,
3423 IN ULONG Key OPTIONAL)
3424 {
3425 PFILE_OBJECT FileObject = NULL;
3426 PLARGE_INTEGER LocalLength = NULL;
3427 PIRP Irp = NULL;
3428 PIO_STACK_LOCATION StackPtr;
3429 PDEVICE_OBJECT DeviceObject;
3430 KEVENT Event;
3431 BOOLEAN LocalEvent = FALSE;
3432 KPROCESSOR_MODE PreviousMode;
3433 NTSTATUS Status = STATUS_SUCCESS;
3434 LARGE_INTEGER CapturedByteOffset, CapturedLength;
3435 OBJECT_HANDLE_INFORMATION HandleInformation;
3436
3437 PAGED_CODE();
3438
3439 PreviousMode = KeGetPreviousMode();
3440
3441 CapturedByteOffset.QuadPart = 0;
3442 CapturedLength.QuadPart = 0;
3443
3444 /* Get File Object */
3445 Status = ObReferenceObjectByHandle(FileHandle,
3446 0,
3447 IoFileObjectType,
3448 PreviousMode,
3449 (PVOID*)&FileObject,
3450 &HandleInformation);
3451 if (!NT_SUCCESS(Status)) return Status;
3452
3453 if (PreviousMode != KernelMode)
3454 {
3455 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access unless we're
3456 in KernelMode! */
3457 if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_READ_DATA)))
3458 {
3459 DPRINT1("Invalid access rights\n");
3460 ObDereferenceObject(FileObject);
3461 return STATUS_ACCESS_DENIED;
3462 }
3463
3464 _SEH_TRY
3465 {
3466 ProbeForWrite(IoStatusBlock,
3467 sizeof(IO_STATUS_BLOCK),
3468 sizeof(ULONG));
3469 CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
3470 CapturedLength = ProbeForReadLargeInteger(Length);
3471 }
3472 _SEH_HANDLE
3473 {
3474 Status = _SEH_GetExceptionCode();
3475 }
3476 _SEH_END;
3477
3478 if (!NT_SUCCESS(Status))
3479 {
3480 ObDereferenceObject(FileObject);
3481 return Status;
3482 }
3483 }
3484 else
3485 {
3486 CapturedByteOffset = *ByteOffset;
3487 CapturedLength = *Length;
3488 }
3489
3490 /* Check if this is a direct open or not */
3491 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
3492 {
3493 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
3494 }
3495 else
3496 {
3497 DeviceObject = IoGetRelatedDeviceObject(FileObject);
3498 }
3499
3500 /* Check if we should use Sync IO or not */
3501 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
3502 {
3503 /* Use File Object event */
3504 KeClearEvent(&FileObject->Event);
3505 }
3506 else
3507 {
3508 /* Use local event */
3509 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
3510 LocalEvent = TRUE;
3511 }
3512
3513 /* Allocate the IRP */
3514 if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
3515 {
3516 ObDereferenceObject(FileObject);
3517 return STATUS_INSUFFICIENT_RESOURCES;
3518 }
3519
3520 /* Allocate local buffer */
3521 LocalLength = ExAllocatePoolWithTag(NonPagedPool,
3522 sizeof(LARGE_INTEGER),
3523 TAG_LOCK);
3524 if (!LocalLength)
3525 {
3526 IoFreeIrp(Irp);
3527 ObDereferenceObject(FileObject);
3528 return STATUS_INSUFFICIENT_RESOURCES;
3529 }
3530 *LocalLength = CapturedLength;
3531
3532 /* Set up the IRP */
3533 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
3534 Irp->RequestorMode = PreviousMode;
3535 Irp->UserIosb = IoStatusBlock;
3536 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
3537 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
3538 Irp->Tail.Overlay.OriginalFileObject = FileObject;
3539
3540 /* Set up Stack Data */
3541 StackPtr = IoGetNextIrpStackLocation(Irp);
3542 StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
3543 StackPtr->MinorFunction = IRP_MN_UNLOCK_SINGLE;
3544 StackPtr->FileObject = FileObject;
3545
3546 /* Set Parameters */
3547 StackPtr->Parameters.LockControl.Length = LocalLength;
3548 StackPtr->Parameters.LockControl.ByteOffset = CapturedByteOffset;
3549 StackPtr->Parameters.LockControl.Key = Key;
3550
3551 /* Call the Driver */
3552 Status = IoCallDriver(DeviceObject, Irp);
3553 if (Status == STATUS_PENDING)
3554 {
3555 if (LocalEvent)
3556 {
3557 KeWaitForSingleObject(&Event,
3558 Executive,
3559 PreviousMode,
3560 FileObject->Flags & FO_ALERTABLE_IO,
3561 NULL);
3562 Status = IoStatusBlock->Status;
3563 }
3564 else
3565 {
3566 KeWaitForSingleObject(&FileObject->Event,
3567 Executive,
3568 PreviousMode,
3569 FileObject->Flags & FO_ALERTABLE_IO,
3570 NULL);
3571 Status = FileObject->FinalStatus;
3572 }
3573 }
3574
3575 /* Return the Status */
3576 return Status;
3577 }
3578
3579 /*
3580 * NAME EXPORTED
3581 * NtWriteFile
3582 *
3583 * DESCRIPTION
3584 *
3585 * ARGUMENTS
3586 *
3587 * RETURN VALUE
3588 *
3589 * REVISIONS
3590 *
3591 * @implemented
3592 */
3593 NTSTATUS
3594 STDCALL
3595 NtWriteFile (IN HANDLE FileHandle,
3596 IN HANDLE Event OPTIONAL,
3597 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
3598 IN PVOID ApcContext OPTIONAL,
3599 OUT PIO_STATUS_BLOCK IoStatusBlock,
3600 IN PVOID Buffer,
3601 IN ULONG Length,
3602 IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for asynch. operations! */
3603 IN PULONG Key OPTIONAL)
3604 {
3605 OBJECT_HANDLE_INFORMATION ObjectHandleInfo;
3606 NTSTATUS Status = STATUS_SUCCESS;
3607 PFILE_OBJECT FileObject;
3608 PIRP Irp = NULL;
3609 PDEVICE_OBJECT DeviceObject;
3610 PIO_STACK_LOCATION StackPtr;
3611 KPROCESSOR_MODE PreviousMode;
3612 BOOLEAN LocalEvent = FALSE;
3613 PKEVENT EventObject = NULL;
3614 LARGE_INTEGER CapturedByteOffset;
3615 ULONG CapturedKey = 0;
3616 ACCESS_MASK DesiredAccess = FILE_WRITE_DATA;
3617
3618 DPRINT("NtWriteFile(FileHandle 0x%p Buffer 0x%p Length %x ByteOffset 0x%p, "
3619 "IoStatusBlock 0x%p)\n", FileHandle, Buffer, Length, ByteOffset,
3620 IoStatusBlock);
3621
3622 PAGED_CODE();
3623
3624 PreviousMode = KeGetPreviousMode();
3625 CapturedByteOffset.QuadPart = 0;
3626
3627 /* Validate User-Mode Buffers */
3628 if(PreviousMode != KernelMode)
3629 {
3630 _SEH_TRY
3631 {
3632 ProbeForWrite(IoStatusBlock,
3633 sizeof(IO_STATUS_BLOCK),
3634 sizeof(ULONG));
3635
3636 ProbeForRead(Buffer,
3637 Length,
3638 1);
3639 if (ByteOffset != NULL)
3640 {
3641 CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
3642 }
3643
3644 if (Key != NULL)
3645 {
3646 CapturedKey = ProbeForReadUlong(Key);
3647 }
3648 }
3649 _SEH_HANDLE
3650 {
3651 Status = _SEH_GetExceptionCode();
3652 }
3653 _SEH_END;
3654
3655 if(!NT_SUCCESS(Status)) return Status;
3656 }
3657 else
3658 {
3659 if (ByteOffset != NULL)
3660 {
3661 CapturedByteOffset = *ByteOffset;
3662 }
3663 if (Key != NULL)
3664 {
3665 CapturedKey = *Key;
3666 }
3667 }
3668
3669 /* Get File Object */
3670 Status = ObReferenceObjectByHandle(FileHandle,
3671 0,
3672 IoFileObjectType,
3673 PreviousMode,
3674 (PVOID*)&FileObject,
3675 &ObjectHandleInfo);
3676 if (!NT_SUCCESS(Status)) return Status;
3677
3678 /* check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
3679 granted. However, if this is a named pipe, make sure we don't ask for
3680 FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
3681 access right! */
3682 if (!(FileObject->Flags & FO_NAMED_PIPE))
3683 DesiredAccess |= FILE_APPEND_DATA;
3684 if (!RtlAreAnyAccessesGranted(ObjectHandleInfo.GrantedAccess,
3685 DesiredAccess))
3686 {
3687 ObDereferenceObject(FileObject);
3688 return STATUS_ACCESS_DENIED;
3689 }
3690
3691 /* Check if we got write Access */
3692 if (ObjectHandleInfo.GrantedAccess & FILE_WRITE_DATA)
3693 {
3694 /* Check the Byte Offset */
3695 if (ByteOffset == NULL ||
3696 (CapturedByteOffset.u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
3697 CapturedByteOffset.u.HighPart == -1))
3698 {
3699 /* a valid ByteOffset is required if asynch. op. */
3700 if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
3701 {
3702 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
3703 ObDereferenceObject(FileObject);
3704 return STATUS_INVALID_PARAMETER;
3705 }
3706
3707 /* Use the Current Byte OFfset */
3708 CapturedByteOffset = FileObject->CurrentByteOffset;
3709 }
3710 }
3711 else if ((ObjectHandleInfo.GrantedAccess & FILE_APPEND_DATA) &&
3712 !(FileObject->Flags & FO_NAMED_PIPE))
3713 {
3714 /* a valid ByteOffset is required if asynch. op. */
3715 if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
3716 {
3717 DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
3718 ObDereferenceObject(FileObject);
3719 return STATUS_INVALID_PARAMETER;
3720 }
3721
3722 /* Give the drivers somethign to understand */
3723 CapturedByteOffset.u.LowPart = FILE_WRITE_TO_END_OF_FILE;
3724 CapturedByteOffset.u.HighPart = 0xffffffff;
3725 }
3726
3727 /* Check if we got an event */
3728 if (Event)
3729 {
3730 /* Reference it */
3731 Status = ObReferenceObjectByHandle(Event,
3732 EVENT_MODIFY_STATE,
3733 ExEventObjectType,
3734 PreviousMode,
3735 (PVOID*)&EventObject,
3736 NULL);
3737 if (!NT_SUCCESS(Status))
3738 {
3739 ObDereferenceObject(FileObject);
3740 return Status;
3741 }
3742 KeClearEvent(EventObject);
3743 }
3744
3745 /* Check if this is a direct open or not */
3746 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
3747 {
3748 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
3749 }
3750 else
3751 {
3752 DeviceObject = IoGetRelatedDeviceObject(FileObject);
3753 }
3754
3755 /* Check if we should use Sync IO or not */
3756 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
3757 {
3758 /* Use File Object event */
3759 KeClearEvent(&FileObject->Event);
3760 }
3761 else
3762 {
3763 LocalEvent = TRUE;
3764 }
3765
3766 /* Build the IRP */
3767 _SEH_TRY
3768 {
3769 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
3770 DeviceObject,
3771 Buffer,
3772 Length,
3773 &CapturedByteOffset,
3774 EventObject,
3775 IoStatusBlock);
3776 if (Irp == NULL)
3777 {
3778 Status = STATUS_INSUFFICIENT_RESOURCES;
3779 }
3780 }
3781 _SEH_HANDLE
3782 {
3783 Status = _SEH_GetExceptionCode();
3784 }
3785 _SEH_END;
3786
3787 /* Cleanup on failure */
3788 if (!NT_SUCCESS(Status))
3789 {
3790 if (Event)
3791 {
3792 ObDereferenceObject(&EventObject);
3793 }
3794 ObDereferenceObject(FileObject);
3795 return Status;
3796 }
3797
3798 /* Set up IRP Data */
3799 Irp->Tail.Overlay.OriginalFileObject = FileObject;
3800 Irp->RequestorMode = PreviousMode;
3801 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
3802 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
3803 Irp->Flags |= IRP_WRITE_OPERATION;
3804 #if 0
3805 /* FIXME:
3806 * Vfat doesn't handle non cached files correctly.
3807 */
3808 if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) Irp->Flags |= IRP_NOCACHE;
3809 #endif
3810
3811 /* Setup Stack Data */
3812 StackPtr = IoGetNextIrpStackLocation(Irp);
3813 StackPtr->FileObject = FileObject;
3814 StackPtr->Parameters.Write.Key = CapturedKey;
3815 if (FileObject->Flags & FO_WRITE_THROUGH) StackPtr->Flags = SL_WRITE_THROUGH;
3816
3817 /* Call the Driver */
3818 Status = IoCallDriver(DeviceObject, Irp);
3819 if (Status == STATUS_PENDING)
3820 {
3821 if (!LocalEvent)
3822 {
3823 KeWaitForSingleObject(&FileObject->Event,
3824 Executive,
3825 PreviousMode,
3826 FileObject->Flags & FO_ALERTABLE_IO,
3827 NULL);
3828 Status = FileObject->FinalStatus;
3829 }
3830 }
3831
3832 /* Return the Status */
3833 return Status;
3834 }
3835
3836 /*
3837 * NAME EXPORTED
3838 * NtWriteFileGather
3839 *
3840 * DESCRIPTION
3841 *
3842 * ARGUMENTS
3843 *
3844 * RETURN VALUE
3845 *
3846 * REVISIONS
3847 */
3848 NTSTATUS
3849 STDCALL
3850 NtWriteFileGather(IN HANDLE FileHandle,
3851 IN HANDLE Event OPTIONAL,
3852 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
3853 IN PVOID UserApcContext OPTIONAL,
3854 OUT PIO_STATUS_BLOCK UserIoStatusBlock,
3855 IN FILE_SEGMENT_ELEMENT BufferDescription [],
3856 IN ULONG BufferLength,
3857 IN PLARGE_INTEGER ByteOffset,
3858 IN PULONG Key OPTIONAL)
3859 {
3860 UNIMPLEMENTED;
3861 return(STATUS_NOT_IMPLEMENTED);
3862 }
3863 /* EOF */