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