Grrr..it's getting late or something. CORRECT fix.
[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;
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 ProbeForWrite(Buffer,
2461 Length,
2462 sizeof(ULONG));
2463 }
2464 _SEH_HANDLE
2465 {
2466 Status = _SEH_GetExceptionCode();
2467 }
2468 _SEH_END;
2469
2470 if(!NT_SUCCESS(Status)) return Status;
2471 }
2472
2473 /* Get File Object */
2474 Status = ObReferenceObjectByHandle(FileHandle,
2475 FILE_READ_DATA,
2476 IoFileObjectType,
2477 PreviousMode,
2478 (PVOID*)&FileObject,
2479 NULL);
2480 if (!NT_SUCCESS(Status)) return Status;
2481
2482 /* Check the Byte Offset */
2483 if (!ByteOffset ||
2484 (ByteOffset->u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
2485 ByteOffset->u.HighPart == 0xffffffff))
2486 {
2487 /* a valid ByteOffset is required if asynch. op. */
2488 if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
2489 {
2490 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
2491 ObDereferenceObject(FileObject);
2492 return STATUS_INVALID_PARAMETER;
2493 }
2494
2495 /* Use the Current Byte OFfset */
2496 ByteOffset = &FileObject->CurrentByteOffset;
2497 }
2498
2499 /* Check for event */
2500 if (Event)
2501 {
2502 /* Reference it */
2503 Status = ObReferenceObjectByHandle(Event,
2504 EVENT_MODIFY_STATE,
2505 ExEventObjectType,
2506 PreviousMode,
2507 (PVOID*)&EventObject,
2508 NULL);
2509 if (!NT_SUCCESS(Status))
2510 {
2511 ObDereferenceObject(FileObject);
2512 return Status;
2513 }
2514 KeClearEvent(EventObject);
2515 }
2516
2517 /* Check if this is a direct open or not */
2518 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
2519 {
2520 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
2521 }
2522 else
2523 {
2524 DeviceObject = IoGetRelatedDeviceObject(FileObject);
2525 }
2526
2527 /* Check if we should use Sync IO or not */
2528 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
2529 {
2530 /* Use File Object event */
2531 KeClearEvent(&FileObject->Event);
2532 }
2533 else
2534 {
2535 LocalEvent = TRUE;
2536 }
2537
2538 /* Create the IRP */
2539 _SEH_TRY
2540 {
2541 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
2542 DeviceObject,
2543 Buffer,
2544 Length,
2545 ByteOffset,
2546 EventObject,
2547 IoStatusBlock);
2548 }
2549 _SEH_HANDLE
2550 {
2551 Status = _SEH_GetExceptionCode();
2552 }
2553 _SEH_END;
2554
2555 /* Cleanup if IRP Allocation Failed */
2556 if (!NT_SUCCESS(Status) || !Irp)
2557 {
2558 if (Event) ObDereferenceObject(EventObject);
2559 ObDereferenceObject(FileObject);
2560 if (Irp)
2561 {
2562 IoFreeIrp(Irp);
2563 }
2564 return NT_SUCCESS(Status) ? STATUS_INSUFFICIENT_RESOURCES : Status;
2565 }
2566
2567 /* Set up IRP Data */
2568 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2569 Irp->RequestorMode = PreviousMode;
2570 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
2571 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
2572 Irp->Flags |= IRP_READ_OPERATION;
2573
2574 #if 0
2575 /* FIXME: KDBG is using this flag and not reading from cluster-aligned. Investigate */
2576 if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING)
2577 {
2578 DbgBreakPoint();
2579 Irp->Flags |= IRP_NOCACHE;
2580 DPRINT1("It's us: %p\n", FileObject);
2581 }
2582 #endif
2583
2584 /* Setup Stack Data */
2585 StackPtr = IoGetNextIrpStackLocation(Irp);
2586 StackPtr->FileObject = FileObject;
2587 StackPtr->Parameters.Read.Key = Key ? *Key : 0;
2588
2589 /* Call the Driver */
2590 Status = IoCallDriver(DeviceObject, Irp);
2591 if (Status == STATUS_PENDING)
2592 {
2593 if (!LocalEvent)
2594 {
2595 KeWaitForSingleObject(&FileObject->Event,
2596 Executive,
2597 PreviousMode,
2598 FileObject->Flags & FO_ALERTABLE_IO,
2599 NULL);
2600 Status = FileObject->FinalStatus;
2601 }
2602 }
2603
2604 /* Return the Status */
2605 return Status;
2606 }
2607
2608 /*
2609 * NAME EXPORTED
2610 * NtReadFileScatter
2611 *
2612 * DESCRIPTION
2613 *
2614 * ARGUMENTS
2615 *
2616 * RETURN VALUE
2617 *
2618 * REVISIONS
2619 */
2620 NTSTATUS
2621 STDCALL
2622 NtReadFileScatter(IN HANDLE FileHandle,
2623 IN HANDLE Event OPTIONAL,
2624 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
2625 IN PVOID UserApcContext OPTIONAL,
2626 OUT PIO_STATUS_BLOCK UserIoStatusBlock,
2627 IN FILE_SEGMENT_ELEMENT BufferDescription [],
2628 IN ULONG BufferLength,
2629 IN PLARGE_INTEGER ByteOffset,
2630 IN PULONG Key OPTIONAL)
2631 {
2632 UNIMPLEMENTED;
2633 return(STATUS_NOT_IMPLEMENTED);
2634 }
2635
2636 /*
2637 * @unimplemented
2638 */
2639 NTSTATUS
2640 STDCALL
2641 NtSetEaFile(IN HANDLE FileHandle,
2642 IN PIO_STATUS_BLOCK IoStatusBlock,
2643 IN PVOID EaBuffer,
2644 IN ULONG EaBufferSize)
2645 {
2646 UNIMPLEMENTED;
2647 return STATUS_NOT_IMPLEMENTED;
2648 }
2649
2650 /*
2651 * @implemented
2652 */
2653 NTSTATUS STDCALL
2654 NtSetInformationFile(HANDLE FileHandle,
2655 PIO_STATUS_BLOCK IoStatusBlock,
2656 PVOID FileInformation,
2657 ULONG Length,
2658 FILE_INFORMATION_CLASS FileInformationClass)
2659 {
2660 OBJECT_HANDLE_INFORMATION HandleInformation;
2661 PIO_STACK_LOCATION StackPtr;
2662 PFILE_OBJECT FileObject;
2663 PDEVICE_OBJECT DeviceObject;
2664 PIRP Irp;
2665 NTSTATUS Status;
2666 PVOID SystemBuffer;
2667 KPROCESSOR_MODE PreviousMode;
2668 BOOLEAN Failed = FALSE;
2669
2670 ASSERT(IoStatusBlock != NULL);
2671 ASSERT(FileInformation != NULL);
2672
2673 DPRINT("NtSetInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
2674 "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
2675 Length, FileInformationClass);
2676
2677 PreviousMode = ExGetPreviousMode();
2678
2679 /* Get the file object from the file handle */
2680 Status = ObReferenceObjectByHandle(FileHandle,
2681 0,
2682 IoFileObjectType,
2683 PreviousMode,
2684 (PVOID *)&FileObject,
2685 &HandleInformation);
2686 if (!NT_SUCCESS(Status))
2687 {
2688 return Status;
2689 }
2690
2691 /* Check information class specific access rights */
2692 switch (FileInformationClass)
2693 {
2694 case FileBasicInformation:
2695 if (!(HandleInformation.GrantedAccess & FILE_WRITE_ATTRIBUTES))
2696 Failed = TRUE;
2697 break;
2698
2699 case FileDispositionInformation:
2700 if (!(HandleInformation.GrantedAccess & DELETE))
2701 Failed = TRUE;
2702 break;
2703
2704 case FilePositionInformation:
2705 if (!(HandleInformation.GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA)) ||
2706 !(FileObject->Flags & FO_SYNCHRONOUS_IO))
2707 Failed = TRUE;
2708 break;
2709
2710 case FileEndOfFileInformation:
2711 if (!(HandleInformation.GrantedAccess & FILE_WRITE_DATA))
2712 Failed = TRUE;
2713 break;
2714
2715 default:
2716 break;
2717 }
2718
2719 if (Failed)
2720 {
2721 DPRINT1("NtSetInformationFile() returns STATUS_ACCESS_DENIED!\n");
2722 ObDereferenceObject(FileObject);
2723 return STATUS_ACCESS_DENIED;
2724 }
2725
2726 DPRINT("FileObject %x\n", FileObject);
2727
2728 /* io completion port? */
2729 if (FileInformationClass == FileCompletionInformation)
2730 {
2731 PKQUEUE Queue;
2732
2733 if (Length < sizeof(FILE_COMPLETION_INFORMATION))
2734 {
2735 Status = STATUS_INFO_LENGTH_MISMATCH;
2736 }
2737 else
2738 {
2739 Status = ObReferenceObjectByHandle(((PFILE_COMPLETION_INFORMATION)FileInformation)->IoCompletionHandle,
2740 IO_COMPLETION_MODIFY_STATE,//???
2741 ExIoCompletionType,
2742 PreviousMode,
2743 (PVOID*)&Queue,
2744 NULL);
2745 if (NT_SUCCESS(Status))
2746 {
2747 /* FIXME: maybe use lookaside list */
2748 FileObject->CompletionContext = ExAllocatePool(NonPagedPool, sizeof(IO_COMPLETION_CONTEXT));
2749 FileObject->CompletionContext->Key = ((PFILE_COMPLETION_INFORMATION)FileInformation)->CompletionKey;
2750 FileObject->CompletionContext->Port = Queue;
2751
2752 ObDereferenceObject(Queue);
2753 }
2754 }
2755
2756 ObDereferenceObject(FileObject);
2757 return Status;
2758 }
2759
2760 DeviceObject = FileObject->DeviceObject;
2761
2762 Irp = IoAllocateIrp(DeviceObject->StackSize,
2763 TRUE);
2764 if (Irp == NULL)
2765 {
2766 ObDereferenceObject(FileObject);
2767 return STATUS_INSUFFICIENT_RESOURCES;
2768 }
2769
2770 SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
2771 Length,
2772 TAG_SYSB);
2773 if (SystemBuffer == NULL)
2774 {
2775 IoFreeIrp(Irp);
2776 ObDereferenceObject(FileObject);
2777 return STATUS_INSUFFICIENT_RESOURCES;
2778 }
2779
2780 MmSafeCopyFromUser(SystemBuffer,
2781 FileInformation,
2782 Length);
2783
2784 /* Trigger FileObject/Event dereferencing */
2785 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2786 Irp->RequestorMode = PreviousMode;
2787 Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
2788 Irp->UserIosb = IoStatusBlock;
2789 Irp->UserEvent = &FileObject->Event;
2790 KeResetEvent(&FileObject->Event);
2791 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2792
2793 StackPtr = IoGetNextIrpStackLocation(Irp);
2794 StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION;
2795 StackPtr->MinorFunction = 0;
2796 StackPtr->Flags = 0;
2797 StackPtr->Control = 0;
2798 StackPtr->DeviceObject = DeviceObject;
2799 StackPtr->FileObject = FileObject;
2800
2801 StackPtr->Parameters.SetFile.FileInformationClass =
2802 FileInformationClass;
2803 StackPtr->Parameters.SetFile.Length = Length;
2804
2805 /*
2806 * Pass the IRP to the FSD (and wait for
2807 * it if required)
2808 */
2809 DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
2810 Status = IoCallDriver(FileObject->DeviceObject,
2811 Irp);
2812 if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
2813 {
2814 KeWaitForSingleObject(&FileObject->Event,
2815 Executive,
2816 PreviousMode,
2817 FileObject->Flags & FO_ALERTABLE_IO,
2818 NULL);
2819 Status = IoStatusBlock->Status;
2820 }
2821
2822 ExFreePool(SystemBuffer);
2823
2824 return Status;
2825 }
2826
2827 /*
2828 * @unimplemented
2829 */
2830 NTSTATUS
2831 STDCALL
2832 NtSetQuotaInformationFile(HANDLE FileHandle,
2833 PIO_STATUS_BLOCK IoStatusBlock,
2834 PFILE_USER_QUOTA_INFORMATION Buffer,
2835 ULONG BufferLength)
2836 {
2837 UNIMPLEMENTED;
2838 return STATUS_NOT_IMPLEMENTED;
2839 }
2840
2841 /*
2842 * @unimplemented
2843 */
2844 NTSTATUS
2845 STDCALL
2846 NtUnlockFile(IN HANDLE FileHandle,
2847 OUT PIO_STATUS_BLOCK IoStatusBlock,
2848 IN PLARGE_INTEGER ByteOffset,
2849 IN PLARGE_INTEGER Length,
2850 OUT PULONG Key OPTIONAL)
2851 {
2852 PFILE_OBJECT FileObject = NULL;
2853 PLARGE_INTEGER LocalLength = NULL;
2854 PIRP Irp = NULL;
2855 PIO_STACK_LOCATION StackPtr;
2856 PDEVICE_OBJECT DeviceObject;
2857 KPROCESSOR_MODE PreviousMode;
2858 NTSTATUS Status;
2859
2860 // FIXME: instead of this, use SEH when available
2861 if (!Length || !ByteOffset)
2862 {
2863 Status = STATUS_INVALID_PARAMETER;
2864 goto fail;
2865 }
2866
2867 PreviousMode = ExGetPreviousMode();
2868
2869 /*
2870 * BUGBUG: ObReferenceObjectByHandle fails if DesiredAccess=0 and mode=UserMode
2871 * It should ONLY fail if we desire an access that conflict with granted access!
2872 */
2873 Status = ObReferenceObjectByHandle(FileHandle,
2874 0, //FILE_READ_DATA,//BUGBUG: have to use something...but shouldn't have to!
2875 IoFileObjectType,
2876 PreviousMode,
2877 (PVOID*)&FileObject,
2878 NULL);
2879 if (!NT_SUCCESS(Status))
2880 {
2881 goto fail;
2882 }
2883
2884 DeviceObject = IoGetRelatedDeviceObject(FileObject);
2885
2886 Irp = IoAllocateIrp(DeviceObject->StackSize,
2887 TRUE);
2888 if (Irp == NULL)
2889 {
2890 Status = STATUS_INSUFFICIENT_RESOURCES;
2891 goto fail;
2892 }
2893
2894 /* Trigger FileObject/Event dereferencing */
2895 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2896 Irp->RequestorMode = PreviousMode;
2897 Irp->UserIosb = IoStatusBlock;
2898 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2899
2900 StackPtr = IoGetNextIrpStackLocation(Irp);
2901 StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
2902 StackPtr->MinorFunction = IRP_MN_UNLOCK_SINGLE;
2903 StackPtr->DeviceObject = DeviceObject;
2904 StackPtr->FileObject = FileObject;
2905
2906 LocalLength = ExAllocatePoolWithTag(NonPagedPool,
2907 sizeof(LARGE_INTEGER),
2908 TAG_LOCK);
2909 if (!LocalLength)
2910 {
2911 Status = STATUS_INSUFFICIENT_RESOURCES;
2912 goto fail;
2913 }
2914
2915 *LocalLength = *Length;
2916
2917 StackPtr->Parameters.LockControl.Length = LocalLength;
2918 StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset;
2919 StackPtr->Parameters.LockControl.Key = Key ? *Key : 0;
2920
2921 /* Allways synchronous */
2922 Status = IofCallDriver(DeviceObject, Irp);
2923
2924 ExFreePool(LocalLength);
2925
2926 return Status;
2927
2928 fail:;
2929 if (LocalLength)
2930 ExFreePool(LocalLength);
2931
2932 if (Irp)
2933 IoFreeIrp(Irp);
2934
2935 if (FileObject)
2936 ObDereferenceObject(FileObject);
2937
2938 return Status;
2939 }
2940
2941 /*
2942 * NAME EXPORTED
2943 * NtWriteFile
2944 *
2945 * DESCRIPTION
2946 *
2947 * ARGUMENTS
2948 *
2949 * RETURN VALUE
2950 *
2951 * REVISIONS
2952 *
2953 * @implemented
2954 */
2955 NTSTATUS
2956 STDCALL
2957 NtWriteFile (IN HANDLE FileHandle,
2958 IN HANDLE Event OPTIONAL,
2959 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
2960 IN PVOID ApcContext OPTIONAL,
2961 OUT PIO_STATUS_BLOCK IoStatusBlock,
2962 IN PVOID Buffer,
2963 IN ULONG Length,
2964 IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for asynch. operations! */
2965 IN PULONG Key OPTIONAL)
2966 {
2967 OBJECT_HANDLE_INFORMATION HandleInformation;
2968 NTSTATUS Status;
2969 PFILE_OBJECT FileObject;
2970 PIRP Irp = NULL;
2971 PIO_STACK_LOCATION StackPtr;
2972 KPROCESSOR_MODE PreviousMode;
2973 PKEVENT EventObject = NULL;
2974 LARGE_INTEGER Offset;
2975
2976 DPRINT("NtWriteFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
2977 "IoStatusBlock %x)\n", FileHandle, Buffer, Length, ByteOffset,
2978 IoStatusBlock);
2979
2980 if (IoStatusBlock == NULL)
2981 return STATUS_ACCESS_VIOLATION;
2982
2983 PreviousMode = ExGetPreviousMode();
2984
2985 Status = ObReferenceObjectByHandle(FileHandle,
2986 0,
2987 IoFileObjectType,
2988 PreviousMode,
2989 (PVOID*)&FileObject,
2990 &HandleInformation);
2991 if (!NT_SUCCESS(Status))
2992 {
2993 return Status;
2994 }
2995
2996 /* Must have FILE_WRITE_DATA | FILE_APPEND_DATA access */
2997 if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)))
2998 {
2999 DPRINT1("Invalid access rights\n");
3000 ObDereferenceObject(FileObject);
3001 return STATUS_ACCESS_DENIED;
3002 }
3003
3004 if (HandleInformation.GrantedAccess & FILE_WRITE_DATA)
3005 {
3006 if (ByteOffset == NULL)
3007 {
3008 /* a valid ByteOffset is required if asynch. op. */
3009 if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
3010 {
3011 DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
3012 ObDereferenceObject(FileObject);
3013 return STATUS_INVALID_PARAMETER;
3014 }
3015
3016 ByteOffset = &FileObject->CurrentByteOffset;
3017 }
3018 }
3019 else if (HandleInformation.GrantedAccess & FILE_APPEND_DATA)
3020 {
3021 /* a valid ByteOffset is required if asynch. op. */
3022 if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
3023 {
3024 DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
3025 ObDereferenceObject(FileObject);
3026 return STATUS_INVALID_PARAMETER;
3027 }
3028
3029 Offset.u.LowPart = FILE_WRITE_TO_END_OF_FILE;
3030 Offset.u.HighPart = 0xffffffff;
3031 ByteOffset = &Offset;
3032 }
3033
3034 if (Event != NULL)
3035 {
3036 Status = ObReferenceObjectByHandle(Event,
3037 SYNCHRONIZE,
3038 ExEventObjectType,
3039 PreviousMode,
3040 (PVOID*)&EventObject,
3041 NULL);
3042 if (!NT_SUCCESS(Status))
3043 {
3044 ObDereferenceObject(FileObject);
3045 return Status;
3046 }
3047
3048 KeClearEvent(EventObject);
3049 }
3050
3051 _SEH_TRY
3052 {
3053 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
3054 FileObject->DeviceObject,
3055 Buffer,
3056 Length,
3057 ByteOffset,
3058 EventObject,
3059 IoStatusBlock);
3060 }
3061 _SEH_HANDLE
3062 {
3063 Status = _SEH_GetExceptionCode();
3064 }
3065 _SEH_END;
3066
3067 if (!NT_SUCCESS(Status) || Irp == NULL)
3068 {
3069 if (Event)
3070 {
3071 ObDereferenceObject(&EventObject);
3072 }
3073 ObDereferenceObject(FileObject);
3074 if (Irp)
3075 {
3076 IoFreeIrp(Irp);
3077 }
3078 return NT_SUCCESS(Status) ? STATUS_INSUFFICIENT_RESOURCES : Status;
3079 }
3080
3081 KeClearEvent(&FileObject->Event);
3082
3083 /* Trigger FileObject/Event dereferencing */
3084 Irp->Tail.Overlay.OriginalFileObject = FileObject;
3085
3086 Irp->RequestorMode = PreviousMode;
3087
3088 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
3089 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
3090
3091 StackPtr = IoGetNextIrpStackLocation(Irp);
3092 StackPtr->FileObject = FileObject;
3093 StackPtr->Parameters.Write.Key = Key ? *Key : 0;
3094
3095 Status = IoCallDriver(FileObject->DeviceObject, Irp);
3096 if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
3097 {
3098 Status = KeWaitForSingleObject(&FileObject->Event,
3099 Executive,
3100 PreviousMode,
3101 FileObject->Flags & FO_ALERTABLE_IO,
3102 NULL);
3103 if (Status != STATUS_WAIT_0)
3104 {
3105 /* Wait failed. */
3106 return Status;
3107 }
3108
3109 Status = IoStatusBlock->Status;
3110 }
3111
3112 return Status;
3113 }
3114
3115 /*
3116 * NAME EXPORTED
3117 * NtWriteFileGather
3118 *
3119 * DESCRIPTION
3120 *
3121 * ARGUMENTS
3122 *
3123 * RETURN VALUE
3124 *
3125 * REVISIONS
3126 */
3127 NTSTATUS
3128 STDCALL
3129 NtWriteFileGather(IN HANDLE FileHandle,
3130 IN HANDLE Event OPTIONAL,
3131 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
3132 IN PVOID UserApcContext OPTIONAL,
3133 OUT PIO_STATUS_BLOCK UserIoStatusBlock,
3134 IN FILE_SEGMENT_ELEMENT BufferDescription [],
3135 IN ULONG BufferLength,
3136 IN PLARGE_INTEGER ByteOffset,
3137 IN PULONG Key OPTIONAL)
3138 {
3139 UNIMPLEMENTED;
3140 return(STATUS_NOT_IMPLEMENTED);
3141 }
3142 /* EOF */