From Eugene Ingerman:
[reactos.git] / reactos / ntoskrnl / io / create.c
1 /* $Id: create.c,v 1.44 2001/06/14 21:05:07 jfilby Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/create.c
6 * PURPOSE: Handling file create/open apis
7 * PROGRAMMER: David Welch (welch@cwcom.net)
8 * UPDATE HISTORY:
9 * 24/05/98: Created
10 */
11
12 /* INCLUDES ***************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <internal/ob.h>
16 #include <internal/io.h>
17 #include <internal/id.h>
18 #include <internal/pool.h>
19
20 #define NDEBUG
21 #include <internal/debug.h>
22
23 /* GLOBALS *******************************************************************/
24
25 #define TAG_FILE_NAME TAG('F', 'N', 'A', 'M')
26
27 /* FUNCTIONS *************************************************************/
28
29 /**********************************************************************
30 * NAME EXPORTED
31 * NtDeleteFile@4
32 *
33 * DESCRIPTION
34 *
35 * ARGUMENTS
36 * ObjectAttributes
37 * ?
38 *
39 * RETURN VALUE
40 *
41 * REVISIONS
42 *
43 */
44 NTSTATUS STDCALL
45 NtDeleteFile (IN POBJECT_ATTRIBUTES ObjectAttributes)
46 {
47 UNIMPLEMENTED;
48 }
49
50
51 /**********************************************************************
52 * NAME INTERNAL
53 * IopCreateFile
54 *
55 * DESCRIPTION
56 *
57 * ARGUMENTS
58 *
59 * RETURN VALUE
60 *
61 * REVISIONS
62 *
63 */
64 NTSTATUS
65 IopCreateFile (PVOID ObjectBody,
66 PVOID Parent,
67 PWSTR RemainingPath,
68 POBJECT_ATTRIBUTES ObjectAttributes)
69 {
70 PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT) Parent;
71 PFILE_OBJECT FileObject = (PFILE_OBJECT) ObjectBody;
72 NTSTATUS Status;
73
74 DPRINT("IopCreateFile(ObjectBody %x, Parent %x, RemainingPath %S)\n",
75 ObjectBody,
76 Parent,
77 RemainingPath);
78
79 if (NULL == DeviceObject)
80 {
81 /* This is probably an attempt to create a meta fileobject (eg. for FAT)
82 for the cache manager, so return STATUS_SUCCESS */
83 DPRINT("DeviceObject was NULL\n");
84 return (STATUS_SUCCESS);
85 }
86 if (IoDeviceObjectType != BODY_TO_HEADER(Parent)->ObjectType)
87 {
88 CPRINT("Parent is a %S which not a device type\n",
89 BODY_TO_HEADER(Parent)->ObjectType->TypeName.Buffer);
90 return (STATUS_UNSUCCESSFUL);
91 }
92 Status = ObReferenceObjectByPointer (DeviceObject,
93 STANDARD_RIGHTS_REQUIRED,
94 IoDeviceObjectType,
95 UserMode);
96 if (STATUS_SUCCESS != Status)
97 {
98 CHECKPOINT1;
99 return (Status);
100 }
101
102 DeviceObject = IoGetAttachedDevice (DeviceObject);
103
104 DPRINT("DeviceObject %x\n", DeviceObject);
105
106 if (NULL == RemainingPath)
107 {
108 FileObject->Flags = FileObject->Flags | FO_DIRECT_DEVICE_OPEN;
109 FileObject->FileName.Buffer =
110 ExAllocatePoolWithTag(NonPagedPool,
111 (ObjectAttributes->ObjectName->Length+1)*2,
112 TAG_FILE_NAME);
113 FileObject->FileName.Length = ObjectAttributes->ObjectName->Length;
114 FileObject->FileName.MaximumLength =
115 ObjectAttributes->ObjectName->MaximumLength;
116 RtlCopyUnicodeString(&(FileObject->FileName),
117 ObjectAttributes->ObjectName);
118 }
119 else
120 {
121 if ((DeviceObject->DeviceType != FILE_DEVICE_FILE_SYSTEM)
122 && (DeviceObject->DeviceType != FILE_DEVICE_DISK)
123 && (DeviceObject->DeviceType != FILE_DEVICE_NETWORK)
124 && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE)
125 && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT))
126 {
127 CPRINT ("Device was wrong type\n");
128 assert(FALSE);
129 return (STATUS_UNSUCCESSFUL);
130 }
131
132 if (DeviceObject->DeviceType != FILE_DEVICE_NETWORK
133 && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE)
134 && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT))
135 {
136 if (!(DeviceObject->Vpb->Flags & VPB_MOUNTED))
137 {
138 DPRINT("Trying to mount storage device\n");
139 Status = IoTryToMountStorageDevice (DeviceObject);
140 DPRINT("Status %x\n", Status);
141 if (!NT_SUCCESS(Status))
142 {
143 CPRINT("Failed to mount storage device (statux %x)\n",
144 Status);
145 return (Status);
146 }
147 DeviceObject = IoGetAttachedDevice(DeviceObject);
148 }
149 }
150 RtlCreateUnicodeString(&(FileObject->FileName),
151 RemainingPath);
152 }
153 DPRINT("FileObject->FileName.Buffer %S\n",
154 FileObject->FileName.Buffer);
155 FileObject->DeviceObject = DeviceObject;
156 DPRINT("FileObject %x DeviceObject %x\n",
157 FileObject,
158 DeviceObject);
159 FileObject->Vpb = DeviceObject->Vpb;
160 FileObject->Type = InternalFileType;
161
162 return (STATUS_SUCCESS);
163 }
164
165
166 /**********************************************************************
167 * NAME EXPORTED
168 * IoCreateStreamFileObject@8
169 *
170 * DESCRIPTION
171 *
172 * ARGUMENTS
173 * FileObject
174 * ?
175 *
176 * DeviceObject
177 * ?
178 *
179 * RETURN VALUE
180 *
181 * NOTE
182 *
183 * REVISIONS
184 *
185 */
186 PFILE_OBJECT STDCALL
187 IoCreateStreamFileObject(PFILE_OBJECT FileObject,
188 PDEVICE_OBJECT DeviceObject)
189 {
190 HANDLE FileHandle;
191 PFILE_OBJECT CreatedFileObject;
192
193 DPRINT("IoCreateStreamFileObject(FileObject %x, DeviceObject %x)\n",
194 FileObject, DeviceObject);
195
196 assert_irql (PASSIVE_LEVEL);
197
198 CreatedFileObject = ObCreateObject (&FileHandle,
199 STANDARD_RIGHTS_REQUIRED,
200 NULL,
201 IoFileObjectType);
202 if (NULL == CreatedFileObject)
203 {
204 DPRINT("Could not create FileObject\n");
205 return (NULL);
206 }
207
208 if (FileObject != NULL)
209 {
210 DeviceObject = FileObject->DeviceObject;
211 }
212 DeviceObject = IoGetAttachedDevice(DeviceObject);
213
214 DPRINT("DeviceObject %x\n", DeviceObject);
215
216 CreatedFileObject->DeviceObject = DeviceObject;
217 CreatedFileObject->Vpb = DeviceObject->Vpb;
218 CreatedFileObject->Type = InternalFileType;
219 CreatedFileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
220
221 ZwClose (FileHandle);
222
223 return (CreatedFileObject);
224 }
225
226
227 /**********************************************************************
228 * NAME EXPORTED
229 * IoCreateFile@56
230 *
231 * DESCRIPTION
232 * Either causes a new file or directory to be created, or it
233 * opens an existing file, device, directory or volume, giving
234 * the caller a handle for the file object. This handle can be
235 * used by subsequent calls to manipulate data within the file
236 * or the file object's state of attributes.
237 *
238 * ARGUMENTS
239 * FileHandle (OUT)
240 * Points to a variable which receives the file handle
241 * on return;
242 *
243 * DesiredAccess
244 * Desired access to the file;
245 *
246 * ObjectAttributes
247 * Structure describing the file;
248 *
249 * IoStatusBlock (OUT)
250 * Receives information about the operation on return;
251 *
252 * AllocationSize [OPTIONAL]
253 * Initial size of the file in bytes;
254 *
255 * FileAttributes
256 * Attributes to create the file with;
257 *
258 * ShareAccess
259 * Type of shared access the caller would like to the
260 * file;
261 *
262 * CreateDisposition
263 * Specifies what to do, depending on whether the
264 * file already exists;
265 *
266 * CreateOptions
267 * Options for creating a new file;
268 *
269 * EaBuffer [OPTIONAL]
270 * Undocumented;
271 *
272 * EaLength
273 * Undocumented;
274 *
275 * CreateFileType
276 * Type of file (normal, named pipe, mailslot) to create;
277 *
278 * ExtraCreateParameters [OPTIONAL]
279 * Additional creation data for named pipe and mailsots;
280 *
281 * Options
282 * Undocumented.
283 *
284 * RETURN VALUE
285 * Status
286 *
287 * NOTE
288 * Prototype taken from Bo Branten's ntifs.h v15.
289 * Description taken from old NtCreateFile's which is
290 * now a wrapper of this call.
291 *
292 * REVISIONS
293 *
294 */
295 NTSTATUS STDCALL
296 IoCreateFile(
297 OUT PHANDLE FileHandle,
298 IN ACCESS_MASK DesiredAccess,
299 IN POBJECT_ATTRIBUTES ObjectAttributes,
300 OUT PIO_STATUS_BLOCK IoStatusBlock,
301 IN PLARGE_INTEGER AllocationSize OPTIONAL,
302 IN ULONG FileAttributes,
303 IN ULONG ShareAccess,
304 IN ULONG CreateDisposition,
305 IN ULONG CreateOptions,
306 IN PVOID EaBuffer OPTIONAL,
307 IN ULONG EaLength,
308 IN CREATE_FILE_TYPE CreateFileType,
309 IN PVOID ExtraCreateParameters OPTIONAL,
310 IN ULONG Options)
311 {
312 PFILE_OBJECT FileObject;
313 NTSTATUS Status;
314 PIRP Irp;
315 KEVENT Event;
316 PIO_STACK_LOCATION StackLoc;
317
318 DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, "
319 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
320 FileHandle,DesiredAccess,ObjectAttributes,
321 ObjectAttributes->ObjectName->Buffer);
322
323 assert_irql(PASSIVE_LEVEL);
324
325 *FileHandle = 0;
326
327 FileObject = ObCreateObject(FileHandle,
328 DesiredAccess,
329 ObjectAttributes,
330 IoFileObjectType);
331 if (FileObject == NULL)
332 {
333 DPRINT1("ObCreateObject() failed!\n");
334 return (STATUS_UNSUCCESSFUL);
335 }
336 if (CreateOptions & FILE_SYNCHRONOUS_IO_ALERT)
337 {
338 FileObject->Flags |= (FO_ALERTABLE_IO | FO_SYNCHRONOUS_IO);
339 }
340 if (CreateOptions & FILE_SYNCHRONOUS_IO_NONALERT)
341 {
342 FileObject->Flags |= FO_SYNCHRONOUS_IO;
343 }
344 KeInitializeEvent(&FileObject->Lock, NotificationEvent, TRUE);
345 KeInitializeEvent(&Event, NotificationEvent, FALSE);
346
347 DPRINT("FileObject %x\n", FileObject);
348 DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
349 /*
350 * Create a new IRP to hand to
351 * the FS driver: this may fail
352 * due to resource shortage.
353 */
354 Irp = IoAllocateIrp(FileObject->DeviceObject->StackSize, FALSE);
355 if (Irp == NULL)
356 {
357 return (STATUS_UNSUCCESSFUL);
358 }
359
360 Irp->UserIosb = IoStatusBlock; //return iostatus
361 Irp->AssociatedIrp.SystemBuffer = EaBuffer;
362 Irp->Tail.Overlay.AuxiliaryBuffer = (PCHAR)ExtraCreateParameters;
363
364 /*
365 * Get the stack location for the new
366 * IRP and prepare it.
367 */
368 StackLoc = IoGetNextIrpStackLocation(Irp);
369 switch (CreateFileType)
370 {
371 default:
372 case CreateFileTypeNone:
373 StackLoc->MajorFunction = IRP_MJ_CREATE;
374 break;
375
376 case CreateFileTypeNamedPipe:
377 StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
378 break;
379
380 case CreateFileTypeMailslot:
381 StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
382 break;
383 }
384 StackLoc->MinorFunction = 0;
385 StackLoc->Flags = 0;
386 StackLoc->Control = 0;
387 StackLoc->DeviceObject = FileObject->DeviceObject;
388 StackLoc->FileObject = FileObject;
389 StackLoc->Parameters.Create.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
390 StackLoc->Parameters.Create.Options |= (CreateDisposition << 24);
391
392 /*
393 * Now call the driver and
394 * possibly wait if it can
395 * not complete the request
396 * immediately.
397 */
398 Status = IofCallDriver(FileObject->DeviceObject, Irp );
399
400 if (Status == STATUS_PENDING)
401 {
402 KeWaitForSingleObject(&Event,
403 Executive,
404 KernelMode,
405 FALSE,
406 NULL);
407 Status = IoStatusBlock->Status;
408 }
409 if (!NT_SUCCESS(Status))
410 {
411 DPRINT("Failing create request with status %x\n", Status);
412 ZwClose(*FileHandle);
413 (*FileHandle) = 0;
414 }
415
416 assert_irql(PASSIVE_LEVEL);
417
418 DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle));
419
420 return (Status);
421 }
422
423
424 /**********************************************************************
425 * NAME EXPORTED
426 * NtCreateFile@44
427 *
428 * DESCRIPTION
429 * Entry point to call IoCreateFile with
430 * default parameters.
431 *
432 * ARGUMENTS
433 * See IoCreateFile.
434 *
435 * RETURN VALUE
436 * See IoCreateFile.
437 *
438 * REVISIONS
439 * 2000-03-25 (ea)
440 * Code originally in NtCreateFile moved in IoCreateFile.
441 */
442 NTSTATUS STDCALL
443 NtCreateFile(PHANDLE FileHandle,
444 ACCESS_MASK DesiredAccess,
445 POBJECT_ATTRIBUTES ObjectAttributes,
446 PIO_STATUS_BLOCK IoStatusBlock,
447 PLARGE_INTEGER AllocateSize,
448 ULONG FileAttributes,
449 ULONG ShareAccess,
450 ULONG CreateDisposition,
451 ULONG CreateOptions,
452 PVOID EaBuffer,
453 ULONG EaLength)
454 {
455 return IoCreateFile(FileHandle,
456 DesiredAccess,
457 ObjectAttributes,
458 IoStatusBlock,
459 AllocateSize,
460 FileAttributes,
461 ShareAccess,
462 CreateDisposition,
463 CreateOptions,
464 EaBuffer,
465 EaLength,
466 CreateFileTypeNone,
467 NULL,
468 0);
469 }
470
471
472 /**********************************************************************
473 * NAME EXPORTED
474 * NtOpenFile@24
475 *
476 * DESCRIPTION
477 * Opens an existing file (simpler than NtCreateFile).
478 *
479 * ARGUMENTS
480 * FileHandle (OUT)
481 * Variable that receives the file handle on return;
482 *
483 * DesiredAccess
484 * Access desired by the caller to the file;
485 *
486 * ObjectAttributes
487 * Structue describing the file to be opened;
488 *
489 * IoStatusBlock (OUT)
490 * Receives details about the result of the
491 * operation;
492 *
493 * ShareAccess
494 * Type of shared access the caller requires;
495 *
496 * OpenOptions
497 * Options for the file open.
498 *
499 * RETURN VALUE
500 * Status.
501 *
502 * NOTE
503 * Undocumented.
504 */
505 NTSTATUS STDCALL
506 NtOpenFile(PHANDLE FileHandle,
507 ACCESS_MASK DesiredAccess,
508 POBJECT_ATTRIBUTES ObjectAttributes,
509 PIO_STATUS_BLOCK IoStatusBlock,
510 ULONG ShareAccess,
511 ULONG OpenOptions)
512 {
513 return IoCreateFile(FileHandle,
514 DesiredAccess,
515 ObjectAttributes,
516 IoStatusBlock,
517 NULL,
518 0,
519 ShareAccess,
520 FILE_OPEN,
521 OpenOptions,
522 NULL,
523 0,
524 CreateFileTypeNone,
525 NULL,
526 0);
527 }
528
529 /* EOF */