Free the irp after a close operation.
[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
2056 {
2057 PIRP Irp;
2058 PDEVICE_OBJECT DeviceObject;
2059 PFILE_OBJECT FileObject;
2060 PIO_STACK_LOCATION IoStack;
2061 KPROCESSOR_MODE PreviousMode;
2062 NTSTATUS Status = STATUS_SUCCESS;
2063
2064 DPRINT("NtQueryDirectoryFile()\n");
2065
2066 PAGED_CODE();
2067
2068 PreviousMode = ExGetPreviousMode();
2069
2070 if(PreviousMode != KernelMode)
2071 {
2072 _SEH_TRY
2073 {
2074 ProbeForWrite(IoStatusBlock,
2075 sizeof(IO_STATUS_BLOCK),
2076 sizeof(ULONG));
2077 ProbeForWrite(FileInformation,
2078 Length,
2079 sizeof(ULONG));
2080 }
2081 _SEH_HANDLE
2082 {
2083 Status = _SEH_GetExceptionCode();
2084 }
2085 _SEH_END;
2086
2087 if(!NT_SUCCESS(Status))
2088 {
2089 return Status;
2090 }
2091 }
2092
2093 Status = ObReferenceObjectByHandle(FileHandle,
2094 FILE_LIST_DIRECTORY,
2095 IoFileObjectType,
2096 PreviousMode,
2097 (PVOID *)&FileObject,
2098 NULL);
2099
2100 if (Status != STATUS_SUCCESS)
2101 {
2102 return(Status);
2103 }
2104 DeviceObject = FileObject->DeviceObject;
2105
2106 Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
2107 if (Irp==NULL)
2108 {
2109 ObDereferenceObject(FileObject);
2110 return STATUS_UNSUCCESSFUL;
2111 }
2112
2113 /* Trigger FileObject/Event dereferencing */
2114 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2115 Irp->RequestorMode = PreviousMode;
2116 Irp->UserIosb = IoStatusBlock;
2117 Irp->UserEvent = &FileObject->Event;
2118 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2119 KeResetEvent( &FileObject->Event );
2120 Irp->UserBuffer=FileInformation;
2121 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
2122 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
2123
2124 IoStack = IoGetNextIrpStackLocation(Irp);
2125
2126 IoStack->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
2127 IoStack->MinorFunction = IRP_MN_QUERY_DIRECTORY;
2128 IoStack->Flags = 0;
2129 IoStack->Control = 0;
2130 IoStack->DeviceObject = DeviceObject;
2131 IoStack->FileObject = FileObject;
2132
2133 if (RestartScan)
2134 {
2135 IoStack->Flags = IoStack->Flags | SL_RESTART_SCAN;
2136 }
2137 if (ReturnSingleEntry)
2138 {
2139 IoStack->Flags = IoStack->Flags | SL_RETURN_SINGLE_ENTRY;
2140 }
2141 if (((PFILE_DIRECTORY_INFORMATION)FileInformation)->FileIndex != 0)
2142 {
2143 IoStack->Flags = IoStack->Flags | SL_INDEX_SPECIFIED;
2144 }
2145
2146 IoStack->Parameters.QueryDirectory.FileInformationClass =
2147 FileInformationClass;
2148 IoStack->Parameters.QueryDirectory.FileName = FileName;
2149 IoStack->Parameters.QueryDirectory.Length = Length;
2150
2151 Status = IoCallDriver(FileObject->DeviceObject,Irp);
2152 if (Status==STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
2153 {
2154 KeWaitForSingleObject(&FileObject->Event,
2155 Executive,
2156 PreviousMode,
2157 FileObject->Flags & FO_ALERTABLE_IO,
2158 NULL);
2159 Status = IoStatusBlock->Status;
2160 }
2161
2162 return(Status);
2163 }
2164
2165 /*
2166 * @unimplemented
2167 */
2168 NTSTATUS STDCALL
2169 NtQueryEaFile(IN HANDLE FileHandle,
2170 OUT PIO_STATUS_BLOCK IoStatusBlock,
2171 OUT PVOID Buffer,
2172 IN ULONG Length,
2173 IN BOOLEAN ReturnSingleEntry,
2174 IN PVOID EaList OPTIONAL,
2175 IN ULONG EaListLength,
2176 IN PULONG EaIndex OPTIONAL,
2177 IN BOOLEAN RestartScan)
2178 {
2179 UNIMPLEMENTED;
2180 return STATUS_NOT_IMPLEMENTED;
2181 }
2182
2183 NTSTATUS
2184 STDCALL
2185 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
2186 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation)
2187 {
2188 IO_STATUS_BLOCK IoStatusBlock;
2189 HANDLE FileHandle;
2190 NTSTATUS Status;
2191
2192 /* Open the file */
2193 Status = ZwOpenFile (&FileHandle,
2194 SYNCHRONIZE | FILE_READ_ATTRIBUTES,
2195 ObjectAttributes,
2196 &IoStatusBlock,
2197 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
2198 FILE_SYNCHRONOUS_IO_NONALERT);
2199 if (!NT_SUCCESS (Status))
2200 {
2201 DPRINT ("ZwOpenFile() failed (Status %lx)\n", Status);
2202 return Status;
2203 }
2204
2205 /* Get file attributes */
2206 Status = ZwQueryInformationFile (FileHandle,
2207 &IoStatusBlock,
2208 FileInformation,
2209 sizeof(FILE_NETWORK_OPEN_INFORMATION),
2210 FileNetworkOpenInformation);
2211 ZwClose (FileHandle);
2212 if (!NT_SUCCESS (Status))
2213 {
2214 DPRINT ("ZwQueryInformationFile() failed (Status %lx)\n", Status);
2215 }
2216
2217 return Status;
2218 }
2219
2220 /*
2221 * @implemented
2222 */
2223 NTSTATUS STDCALL
2224 NtQueryInformationFile(HANDLE FileHandle,
2225 PIO_STATUS_BLOCK IoStatusBlock,
2226 PVOID FileInformation,
2227 ULONG Length,
2228 FILE_INFORMATION_CLASS FileInformationClass)
2229 {
2230 OBJECT_HANDLE_INFORMATION HandleInformation;
2231 PFILE_OBJECT FileObject;
2232 NTSTATUS Status;
2233 PIRP Irp;
2234 PDEVICE_OBJECT DeviceObject;
2235 PIO_STACK_LOCATION StackPtr;
2236 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
2237 KEVENT Event;
2238 BOOLEAN LocalEvent = FALSE;
2239 BOOLEAN Failed = FALSE;
2240
2241 ASSERT(IoStatusBlock != NULL);
2242 ASSERT(FileInformation != NULL);
2243
2244 DPRINT("NtQueryInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
2245 "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
2246 Length, FileInformationClass);
2247
2248 /* Reference the Handle */
2249 Status = ObReferenceObjectByHandle(FileHandle,
2250 0,
2251 IoFileObjectType,
2252 PreviousMode,
2253 (PVOID *)&FileObject,
2254 &HandleInformation);
2255 if (!NT_SUCCESS(Status)) return Status;
2256
2257 /* Check information class specific access rights */
2258 switch (FileInformationClass)
2259 {
2260 case FileBasicInformation:
2261 if (!(HandleInformation.GrantedAccess & FILE_READ_ATTRIBUTES))
2262 Failed = TRUE;
2263 break;
2264
2265 case FilePositionInformation:
2266 if (!(HandleInformation.GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA)) ||
2267 !(FileObject->Flags & FO_SYNCHRONOUS_IO))
2268 Failed = TRUE;
2269 break;
2270
2271 case FileAlignmentInformation:
2272 if (!(FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING))
2273 Failed = TRUE;
2274 break;
2275
2276 default:
2277 break;
2278 }
2279
2280 if (Failed)
2281 {
2282 DPRINT1("NtQueryInformationFile() returns STATUS_ACCESS_DENIED!\n");
2283 ObDereferenceObject(FileObject);
2284 return STATUS_ACCESS_DENIED;
2285 }
2286
2287 DPRINT("FileObject %x\n", FileObject);
2288
2289 /* Check if this is a direct open or not */
2290 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
2291 {
2292 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
2293 }
2294 else
2295 {
2296 DeviceObject = IoGetRelatedDeviceObject(FileObject);
2297 }
2298
2299 /* Check if we should use Sync IO or not */
2300 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
2301 {
2302 /* Use File Object event */
2303 KeClearEvent(&FileObject->Event);
2304 }
2305 else
2306 {
2307 /* Use local event */
2308 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
2309 LocalEvent = TRUE;
2310 }
2311
2312 /* Allocate the IRP */
2313 if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE)))
2314 {
2315 ObDereferenceObject(FileObject);
2316 return STATUS_INSUFFICIENT_RESOURCES;
2317 }
2318
2319 /* Allocate the System Buffer */
2320 if (!(Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
2321 Length,
2322 TAG_SYSB)))
2323 {
2324 IoFreeIrp(Irp);
2325 ObDereferenceObject(FileObject);
2326 return STATUS_INSUFFICIENT_RESOURCES;
2327 }
2328
2329 /* Set up the IRP */
2330 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2331 Irp->RequestorMode = PreviousMode;
2332 Irp->UserIosb = IoStatusBlock;
2333 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
2334 Irp->UserBuffer = FileInformation;
2335 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2336 Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER | IRP_INPUT_OPERATION;
2337 Irp->Flags |= (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
2338
2339 /* Set up Stack Data */
2340 StackPtr = IoGetNextIrpStackLocation(Irp);
2341 StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
2342 StackPtr->FileObject = FileObject;
2343
2344 /* Set the Parameters */
2345 StackPtr->Parameters.QueryFile.FileInformationClass = FileInformationClass;
2346 StackPtr->Parameters.QueryFile.Length = Length;
2347
2348 /* Call the Driver */
2349 Status = IoCallDriver(DeviceObject, Irp);
2350 if (Status == STATUS_PENDING)
2351 {
2352 if (LocalEvent)
2353 {
2354 KeWaitForSingleObject(&Event,
2355 Executive,
2356 PreviousMode,
2357 FileObject->Flags & FO_ALERTABLE_IO,
2358 NULL);
2359 Status = IoStatusBlock->Status;
2360 }
2361 else
2362 {
2363 KeWaitForSingleObject(&FileObject->Event,
2364 Executive,
2365 PreviousMode,
2366 FileObject->Flags & FO_ALERTABLE_IO,
2367 NULL);
2368 Status = FileObject->FinalStatus;
2369 }
2370 }
2371
2372 /* Return the Status */
2373 return Status;
2374 }
2375
2376 /*
2377 * @unimplemented
2378 */
2379 NTSTATUS
2380 STDCALL
2381 NtQueryQuotaInformationFile(IN HANDLE FileHandle,
2382 OUT PIO_STATUS_BLOCK IoStatusBlock,
2383 OUT PVOID Buffer,
2384 IN ULONG Length,
2385 IN BOOLEAN ReturnSingleEntry,
2386 IN PVOID SidList OPTIONAL,
2387 IN ULONG SidListLength,
2388 IN PSID StartSid OPTIONAL,
2389 IN BOOLEAN RestartScan)
2390 {
2391 UNIMPLEMENTED;
2392 return STATUS_NOT_IMPLEMENTED;
2393 }
2394
2395 /*
2396 * NAME EXPORTED
2397 * NtReadFile
2398 *
2399 * DESCRIPTION
2400 *
2401 * ARGUMENTS
2402 *
2403 * RETURN VALUE
2404 *
2405 * REVISIONS
2406 *
2407 * @implemented
2408 */
2409 NTSTATUS
2410 STDCALL
2411 NtReadFile(IN HANDLE FileHandle,
2412 IN HANDLE Event OPTIONAL,
2413 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
2414 IN PVOID ApcContext OPTIONAL,
2415 OUT PIO_STATUS_BLOCK IoStatusBlock,
2416 OUT PVOID Buffer,
2417 IN ULONG Length,
2418 IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for asynch. operations! */
2419 IN PULONG Key OPTIONAL)
2420 {
2421 NTSTATUS Status;
2422 PFILE_OBJECT FileObject;
2423 PIRP Irp = NULL;
2424 PIO_STACK_LOCATION StackPtr;
2425 KPROCESSOR_MODE PreviousMode;
2426 PKEVENT EventObject = NULL;
2427
2428 DPRINT("NtReadFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
2429 "IoStatusBlock %x)\n", FileHandle, Buffer, Length, ByteOffset,
2430 IoStatusBlock);
2431
2432 if (IoStatusBlock == NULL)
2433 return STATUS_ACCESS_VIOLATION;
2434
2435 PreviousMode = ExGetPreviousMode();
2436
2437 Status = ObReferenceObjectByHandle(FileHandle,
2438 FILE_READ_DATA,
2439 IoFileObjectType,
2440 PreviousMode,
2441 (PVOID*)&FileObject,
2442 NULL);
2443 if (!NT_SUCCESS(Status))
2444 {
2445 return Status;
2446 }
2447
2448 if (ByteOffset == NULL ||
2449 (ByteOffset->u.LowPart == FILE_USE_FILE_POINTER_POSITION &&
2450 ByteOffset->u.HighPart == 0xffffffff))
2451 {
2452 /* a valid ByteOffset is required if asynch. op. */
2453 if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
2454 {
2455 DPRINT1("NtReadFile: missing ByteOffset for asynch. op\n");
2456 ObDereferenceObject(FileObject);
2457 return STATUS_INVALID_PARAMETER;
2458 }
2459
2460 ByteOffset = &FileObject->CurrentByteOffset;
2461 }
2462
2463 if (Event != NULL)
2464 {
2465 Status = ObReferenceObjectByHandle(Event,
2466 SYNCHRONIZE,
2467 ExEventObjectType,
2468 PreviousMode,
2469 (PVOID*)&EventObject,
2470 NULL);
2471 if (!NT_SUCCESS(Status))
2472 {
2473 ObDereferenceObject(FileObject);
2474 return Status;
2475 }
2476
2477 KeClearEvent(EventObject);
2478 }
2479
2480 _SEH_TRY
2481 {
2482 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
2483 FileObject->DeviceObject,
2484 Buffer,
2485 Length,
2486 ByteOffset,
2487 EventObject,
2488 IoStatusBlock);
2489 }
2490 _SEH_HANDLE
2491 {
2492 Status = _SEH_GetExceptionCode();
2493 }
2494 _SEH_END;
2495
2496 if (!NT_SUCCESS(Status) || Irp == NULL)
2497 {
2498 if (Event)
2499 {
2500 ObDereferenceObject(&EventObject);
2501 }
2502 ObDereferenceObject(FileObject);
2503 if (Irp)
2504 {
2505 IoFreeIrp(Irp);
2506 }
2507 return NT_SUCCESS(Status) ? STATUS_INSUFFICIENT_RESOURCES : Status;
2508 }
2509
2510 KeClearEvent(&FileObject->Event);
2511
2512 /* Trigger FileObject/Event dereferencing */
2513 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2514
2515 Irp->RequestorMode = PreviousMode;
2516
2517 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
2518 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
2519
2520 StackPtr = IoGetNextIrpStackLocation(Irp);
2521 StackPtr->FileObject = FileObject;
2522 StackPtr->Parameters.Read.Key = Key ? *Key : 0;
2523
2524 Status = IoCallDriver(FileObject->DeviceObject, Irp);
2525 if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
2526 {
2527 Status = KeWaitForSingleObject(&FileObject->Event,
2528 Executive,
2529 PreviousMode,
2530 FileObject->Flags & FO_ALERTABLE_IO,
2531 NULL);
2532 if (Status != STATUS_WAIT_0)
2533 {
2534 /* Wait failed. */
2535 return Status;
2536 }
2537
2538 Status = IoStatusBlock->Status;
2539 }
2540
2541 return Status;
2542 }
2543
2544 /*
2545 * NAME EXPORTED
2546 * NtReadFileScatter
2547 *
2548 * DESCRIPTION
2549 *
2550 * ARGUMENTS
2551 *
2552 * RETURN VALUE
2553 *
2554 * REVISIONS
2555 */
2556 NTSTATUS
2557 STDCALL
2558 NtReadFileScatter(IN HANDLE FileHandle,
2559 IN HANDLE Event OPTIONAL,
2560 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
2561 IN PVOID UserApcContext OPTIONAL,
2562 OUT PIO_STATUS_BLOCK UserIoStatusBlock,
2563 IN FILE_SEGMENT_ELEMENT BufferDescription [],
2564 IN ULONG BufferLength,
2565 IN PLARGE_INTEGER ByteOffset,
2566 IN PULONG Key OPTIONAL)
2567 {
2568 UNIMPLEMENTED;
2569 return(STATUS_NOT_IMPLEMENTED);
2570 }
2571
2572 /*
2573 * @unimplemented
2574 */
2575 NTSTATUS
2576 STDCALL
2577 NtSetEaFile(IN HANDLE FileHandle,
2578 IN PIO_STATUS_BLOCK IoStatusBlock,
2579 IN PVOID EaBuffer,
2580 IN ULONG EaBufferSize)
2581 {
2582 UNIMPLEMENTED;
2583 return STATUS_NOT_IMPLEMENTED;
2584 }
2585
2586 /*
2587 * @implemented
2588 */
2589 NTSTATUS STDCALL
2590 NtSetInformationFile(HANDLE FileHandle,
2591 PIO_STATUS_BLOCK IoStatusBlock,
2592 PVOID FileInformation,
2593 ULONG Length,
2594 FILE_INFORMATION_CLASS FileInformationClass)
2595 {
2596 OBJECT_HANDLE_INFORMATION HandleInformation;
2597 PIO_STACK_LOCATION StackPtr;
2598 PFILE_OBJECT FileObject;
2599 PDEVICE_OBJECT DeviceObject;
2600 PIRP Irp;
2601 NTSTATUS Status;
2602 PVOID SystemBuffer;
2603 KPROCESSOR_MODE PreviousMode;
2604 BOOLEAN Failed = FALSE;
2605
2606 ASSERT(IoStatusBlock != NULL);
2607 ASSERT(FileInformation != NULL);
2608
2609 DPRINT("NtSetInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
2610 "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
2611 Length, FileInformationClass);
2612
2613 PreviousMode = ExGetPreviousMode();
2614
2615 /* Get the file object from the file handle */
2616 Status = ObReferenceObjectByHandle(FileHandle,
2617 0,
2618 IoFileObjectType,
2619 PreviousMode,
2620 (PVOID *)&FileObject,
2621 &HandleInformation);
2622 if (!NT_SUCCESS(Status))
2623 {
2624 return Status;
2625 }
2626
2627 /* Check information class specific access rights */
2628 switch (FileInformationClass)
2629 {
2630 case FileBasicInformation:
2631 if (!(HandleInformation.GrantedAccess & FILE_WRITE_ATTRIBUTES))
2632 Failed = TRUE;
2633 break;
2634
2635 case FileDispositionInformation:
2636 if (!(HandleInformation.GrantedAccess & DELETE))
2637 Failed = TRUE;
2638 break;
2639
2640 case FilePositionInformation:
2641 if (!(HandleInformation.GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA)) ||
2642 !(FileObject->Flags & FO_SYNCHRONOUS_IO))
2643 Failed = TRUE;
2644 break;
2645
2646 case FileEndOfFileInformation:
2647 if (!(HandleInformation.GrantedAccess & FILE_WRITE_DATA))
2648 Failed = TRUE;
2649 break;
2650
2651 default:
2652 break;
2653 }
2654
2655 if (Failed)
2656 {
2657 DPRINT1("NtSetInformationFile() returns STATUS_ACCESS_DENIED!\n");
2658 ObDereferenceObject(FileObject);
2659 return STATUS_ACCESS_DENIED;
2660 }
2661
2662 DPRINT("FileObject %x\n", FileObject);
2663
2664 /* io completion port? */
2665 if (FileInformationClass == FileCompletionInformation)
2666 {
2667 PKQUEUE Queue;
2668
2669 if (Length < sizeof(FILE_COMPLETION_INFORMATION))
2670 {
2671 Status = STATUS_INFO_LENGTH_MISMATCH;
2672 }
2673 else
2674 {
2675 Status = ObReferenceObjectByHandle(((PFILE_COMPLETION_INFORMATION)FileInformation)->IoCompletionHandle,
2676 IO_COMPLETION_MODIFY_STATE,//???
2677 ExIoCompletionType,
2678 PreviousMode,
2679 (PVOID*)&Queue,
2680 NULL);
2681 if (NT_SUCCESS(Status))
2682 {
2683 /* FIXME: maybe use lookaside list */
2684 FileObject->CompletionContext = ExAllocatePool(NonPagedPool, sizeof(IO_COMPLETION_CONTEXT));
2685 FileObject->CompletionContext->Key = ((PFILE_COMPLETION_INFORMATION)FileInformation)->CompletionKey;
2686 FileObject->CompletionContext->Port = Queue;
2687
2688 ObDereferenceObject(Queue);
2689 }
2690 }
2691
2692 ObDereferenceObject(FileObject);
2693 return Status;
2694 }
2695
2696 DeviceObject = FileObject->DeviceObject;
2697
2698 Irp = IoAllocateIrp(DeviceObject->StackSize,
2699 TRUE);
2700 if (Irp == NULL)
2701 {
2702 ObDereferenceObject(FileObject);
2703 return STATUS_INSUFFICIENT_RESOURCES;
2704 }
2705
2706 SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
2707 Length,
2708 TAG_SYSB);
2709 if (SystemBuffer == NULL)
2710 {
2711 IoFreeIrp(Irp);
2712 ObDereferenceObject(FileObject);
2713 return STATUS_INSUFFICIENT_RESOURCES;
2714 }
2715
2716 MmSafeCopyFromUser(SystemBuffer,
2717 FileInformation,
2718 Length);
2719
2720 /* Trigger FileObject/Event dereferencing */
2721 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2722 Irp->RequestorMode = PreviousMode;
2723 Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
2724 Irp->UserIosb = IoStatusBlock;
2725 Irp->UserEvent = &FileObject->Event;
2726 KeResetEvent(&FileObject->Event);
2727 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2728
2729 StackPtr = IoGetNextIrpStackLocation(Irp);
2730 StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION;
2731 StackPtr->MinorFunction = 0;
2732 StackPtr->Flags = 0;
2733 StackPtr->Control = 0;
2734 StackPtr->DeviceObject = DeviceObject;
2735 StackPtr->FileObject = FileObject;
2736
2737 StackPtr->Parameters.SetFile.FileInformationClass =
2738 FileInformationClass;
2739 StackPtr->Parameters.SetFile.Length = Length;
2740
2741 /*
2742 * Pass the IRP to the FSD (and wait for
2743 * it if required)
2744 */
2745 DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
2746 Status = IoCallDriver(FileObject->DeviceObject,
2747 Irp);
2748 if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
2749 {
2750 KeWaitForSingleObject(&FileObject->Event,
2751 Executive,
2752 PreviousMode,
2753 FileObject->Flags & FO_ALERTABLE_IO,
2754 NULL);
2755 Status = IoStatusBlock->Status;
2756 }
2757
2758 ExFreePool(SystemBuffer);
2759
2760 return Status;
2761 }
2762
2763 /*
2764 * @unimplemented
2765 */
2766 NTSTATUS
2767 STDCALL
2768 NtSetQuotaInformationFile(HANDLE FileHandle,
2769 PIO_STATUS_BLOCK IoStatusBlock,
2770 PFILE_USER_QUOTA_INFORMATION Buffer,
2771 ULONG BufferLength)
2772 {
2773 UNIMPLEMENTED;
2774 return STATUS_NOT_IMPLEMENTED;
2775 }
2776
2777 /*
2778 * @unimplemented
2779 */
2780 NTSTATUS
2781 STDCALL
2782 NtUnlockFile(IN HANDLE FileHandle,
2783 OUT PIO_STATUS_BLOCK IoStatusBlock,
2784 IN PLARGE_INTEGER ByteOffset,
2785 IN PLARGE_INTEGER Length,
2786 OUT PULONG Key OPTIONAL)
2787 {
2788 PFILE_OBJECT FileObject = NULL;
2789 PLARGE_INTEGER LocalLength = NULL;
2790 PIRP Irp = NULL;
2791 PIO_STACK_LOCATION StackPtr;
2792 PDEVICE_OBJECT DeviceObject;
2793 KPROCESSOR_MODE PreviousMode;
2794 NTSTATUS Status;
2795
2796 // FIXME: instead of this, use SEH when available
2797 if (!Length || !ByteOffset)
2798 {
2799 Status = STATUS_INVALID_PARAMETER;
2800 goto fail;
2801 }
2802
2803 PreviousMode = ExGetPreviousMode();
2804
2805 /*
2806 * BUGBUG: ObReferenceObjectByHandle fails if DesiredAccess=0 and mode=UserMode
2807 * It should ONLY fail if we desire an access that conflict with granted access!
2808 */
2809 Status = ObReferenceObjectByHandle(FileHandle,
2810 0, //FILE_READ_DATA,//BUGBUG: have to use something...but shouldn't have to!
2811 IoFileObjectType,
2812 PreviousMode,
2813 (PVOID*)&FileObject,
2814 NULL);
2815 if (!NT_SUCCESS(Status))
2816 {
2817 goto fail;
2818 }
2819
2820 DeviceObject = IoGetRelatedDeviceObject(FileObject);
2821
2822 Irp = IoAllocateIrp(DeviceObject->StackSize,
2823 TRUE);
2824 if (Irp == NULL)
2825 {
2826 Status = STATUS_INSUFFICIENT_RESOURCES;
2827 goto fail;
2828 }
2829
2830 /* Trigger FileObject/Event dereferencing */
2831 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2832 Irp->RequestorMode = PreviousMode;
2833 Irp->UserIosb = IoStatusBlock;
2834 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2835
2836 StackPtr = IoGetNextIrpStackLocation(Irp);
2837 StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
2838 StackPtr->MinorFunction = IRP_MN_UNLOCK_SINGLE;
2839 StackPtr->DeviceObject = DeviceObject;
2840 StackPtr->FileObject = FileObject;
2841
2842 LocalLength = ExAllocatePoolWithTag(NonPagedPool,
2843 sizeof(LARGE_INTEGER),
2844 TAG_LOCK);
2845 if (!LocalLength)
2846 {
2847 Status = STATUS_INSUFFICIENT_RESOURCES;
2848 goto fail;
2849 }
2850
2851 *LocalLength = *Length;
2852
2853 StackPtr->Parameters.LockControl.Length = LocalLength;
2854 StackPtr->Parameters.LockControl.ByteOffset = *ByteOffset;
2855 StackPtr->Parameters.LockControl.Key = Key ? *Key : 0;
2856
2857 /* Allways synchronous */
2858 Status = IofCallDriver(DeviceObject, Irp);
2859
2860 ExFreePool(LocalLength);
2861
2862 return Status;
2863
2864 fail:;
2865 if (LocalLength)
2866 ExFreePool(LocalLength);
2867
2868 if (Irp)
2869 IoFreeIrp(Irp);
2870
2871 if (FileObject)
2872 ObDereferenceObject(FileObject);
2873
2874 return Status;
2875 }
2876
2877 /*
2878 * NAME EXPORTED
2879 * NtWriteFile
2880 *
2881 * DESCRIPTION
2882 *
2883 * ARGUMENTS
2884 *
2885 * RETURN VALUE
2886 *
2887 * REVISIONS
2888 *
2889 * @implemented
2890 */
2891 NTSTATUS
2892 STDCALL
2893 NtWriteFile (IN HANDLE FileHandle,
2894 IN HANDLE Event OPTIONAL,
2895 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
2896 IN PVOID ApcContext OPTIONAL,
2897 OUT PIO_STATUS_BLOCK IoStatusBlock,
2898 IN PVOID Buffer,
2899 IN ULONG Length,
2900 IN PLARGE_INTEGER ByteOffset OPTIONAL, /* NOT optional for asynch. operations! */
2901 IN PULONG Key OPTIONAL)
2902 {
2903 OBJECT_HANDLE_INFORMATION HandleInformation;
2904 NTSTATUS Status;
2905 PFILE_OBJECT FileObject;
2906 PIRP Irp = NULL;
2907 PIO_STACK_LOCATION StackPtr;
2908 KPROCESSOR_MODE PreviousMode;
2909 PKEVENT EventObject = NULL;
2910 LARGE_INTEGER Offset;
2911
2912 DPRINT("NtWriteFile(FileHandle %x Buffer %x Length %x ByteOffset %x, "
2913 "IoStatusBlock %x)\n", FileHandle, Buffer, Length, ByteOffset,
2914 IoStatusBlock);
2915
2916 if (IoStatusBlock == NULL)
2917 return STATUS_ACCESS_VIOLATION;
2918
2919 PreviousMode = ExGetPreviousMode();
2920
2921 Status = ObReferenceObjectByHandle(FileHandle,
2922 0,
2923 IoFileObjectType,
2924 PreviousMode,
2925 (PVOID*)&FileObject,
2926 &HandleInformation);
2927 if (!NT_SUCCESS(Status))
2928 {
2929 return Status;
2930 }
2931
2932 /* Must have FILE_WRITE_DATA | FILE_APPEND_DATA access */
2933 if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)))
2934 {
2935 DPRINT1("Invalid access rights\n");
2936 ObDereferenceObject(FileObject);
2937 return STATUS_ACCESS_DENIED;
2938 }
2939
2940 if (HandleInformation.GrantedAccess & FILE_WRITE_DATA)
2941 {
2942 if (ByteOffset == NULL)
2943 {
2944 /* a valid ByteOffset is required if asynch. op. */
2945 if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
2946 {
2947 DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
2948 ObDereferenceObject(FileObject);
2949 return STATUS_INVALID_PARAMETER;
2950 }
2951
2952 ByteOffset = &FileObject->CurrentByteOffset;
2953 }
2954 }
2955 else if (HandleInformation.GrantedAccess & FILE_APPEND_DATA)
2956 {
2957 /* a valid ByteOffset is required if asynch. op. */
2958 if (!(FileObject->Flags & FO_SYNCHRONOUS_IO))
2959 {
2960 DPRINT1("NtWriteFile: missing ByteOffset for asynch. op\n");
2961 ObDereferenceObject(FileObject);
2962 return STATUS_INVALID_PARAMETER;
2963 }
2964
2965 Offset.u.LowPart = FILE_WRITE_TO_END_OF_FILE;
2966 Offset.u.HighPart = 0xffffffff;
2967 ByteOffset = &Offset;
2968 }
2969
2970 if (Event != NULL)
2971 {
2972 Status = ObReferenceObjectByHandle(Event,
2973 SYNCHRONIZE,
2974 ExEventObjectType,
2975 PreviousMode,
2976 (PVOID*)&EventObject,
2977 NULL);
2978 if (!NT_SUCCESS(Status))
2979 {
2980 ObDereferenceObject(FileObject);
2981 return Status;
2982 }
2983
2984 KeClearEvent(EventObject);
2985 }
2986
2987 _SEH_TRY
2988 {
2989 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
2990 FileObject->DeviceObject,
2991 Buffer,
2992 Length,
2993 ByteOffset,
2994 EventObject,
2995 IoStatusBlock);
2996 }
2997 _SEH_HANDLE
2998 {
2999 Status = _SEH_GetExceptionCode();
3000 }
3001 _SEH_END;
3002
3003 if (!NT_SUCCESS(Status) || Irp == NULL)
3004 {
3005 if (Event)
3006 {
3007 ObDereferenceObject(&EventObject);
3008 }
3009 ObDereferenceObject(FileObject);
3010 if (Irp)
3011 {
3012 IoFreeIrp(Irp);
3013 }
3014 return NT_SUCCESS(Status) ? STATUS_INSUFFICIENT_RESOURCES : Status;
3015 }
3016
3017 KeClearEvent(&FileObject->Event);
3018
3019 /* Trigger FileObject/Event dereferencing */
3020 Irp->Tail.Overlay.OriginalFileObject = FileObject;
3021
3022 Irp->RequestorMode = PreviousMode;
3023
3024 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
3025 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
3026
3027 StackPtr = IoGetNextIrpStackLocation(Irp);
3028 StackPtr->FileObject = FileObject;
3029 StackPtr->Parameters.Write.Key = Key ? *Key : 0;
3030
3031 Status = IoCallDriver(FileObject->DeviceObject, Irp);
3032 if (Status == STATUS_PENDING && (FileObject->Flags & FO_SYNCHRONOUS_IO))
3033 {
3034 Status = KeWaitForSingleObject(&FileObject->Event,
3035 Executive,
3036 PreviousMode,
3037 FileObject->Flags & FO_ALERTABLE_IO,
3038 NULL);
3039 if (Status != STATUS_WAIT_0)
3040 {
3041 /* Wait failed. */
3042 return Status;
3043 }
3044
3045 Status = IoStatusBlock->Status;
3046 }
3047
3048 return Status;
3049 }
3050
3051 /*
3052 * NAME EXPORTED
3053 * NtWriteFileGather
3054 *
3055 * DESCRIPTION
3056 *
3057 * ARGUMENTS
3058 *
3059 * RETURN VALUE
3060 *
3061 * REVISIONS
3062 */
3063 NTSTATUS
3064 STDCALL
3065 NtWriteFileGather(IN HANDLE FileHandle,
3066 IN HANDLE Event OPTIONAL,
3067 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
3068 IN PVOID UserApcContext OPTIONAL,
3069 OUT PIO_STATUS_BLOCK UserIoStatusBlock,
3070 IN FILE_SEGMENT_ELEMENT BufferDescription [],
3071 IN ULONG BufferLength,
3072 IN PLARGE_INTEGER ByteOffset,
3073 IN PULONG Key OPTIONAL)
3074 {
3075 UNIMPLEMENTED;
3076 return(STATUS_NOT_IMPLEMENTED);
3077 }
3078 /* EOF */