sync with trunk r46493
[reactos.git] / drivers / filesystems / cdfs / create.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2002, 2003, 2004 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /* $Id$
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * FILE: services/fs/cdfs/cdfs.c
24 * PURPOSE: CDROM (ISO 9660) filesystem driver
25 * PROGRAMMER: Art Yerkes
26 * Eric Kohl
27 */
28
29 /* INCLUDES *****************************************************************/
30
31 #include "cdfs.h"
32
33 #define NDEBUG
34 #include <debug.h>
35
36 /* FUNCTIONS ****************************************************************/
37
38 static NTSTATUS
39 CdfsMakeAbsoluteFilename(PFILE_OBJECT FileObject,
40 PUNICODE_STRING RelativeFileName,
41 PUNICODE_STRING AbsoluteFileName)
42 {
43 ULONG Length;
44 PFCB Fcb;
45 NTSTATUS Status;
46
47 DPRINT("try related for %wZ\n", RelativeFileName);
48 Fcb = FileObject->FsContext;
49 ASSERT(Fcb);
50
51 /* verify related object is a directory and target name
52 don't start with \. */
53 if ((Fcb->Entry.FileFlags & FILE_FLAG_DIRECTORY) == 0 ||
54 RelativeFileName->Buffer[0] == L'\\')
55 {
56 return STATUS_INVALID_PARAMETER;
57 }
58
59 /* construct absolute path name */
60 Length = (wcslen(Fcb->PathName) * sizeof(WCHAR)) +
61 sizeof(WCHAR) +
62 RelativeFileName->Length +
63 sizeof(WCHAR);
64 AbsoluteFileName->Length = 0;
65 AbsoluteFileName->MaximumLength = Length;
66 AbsoluteFileName->Buffer = ExAllocatePool(NonPagedPool,
67 Length);
68 if (AbsoluteFileName->Buffer == NULL)
69 {
70 return STATUS_INSUFFICIENT_RESOURCES;
71 }
72
73 Status = RtlAppendUnicodeToString(AbsoluteFileName,
74 Fcb->PathName);
75 if (!NT_SUCCESS(Status))
76 {
77 RtlFreeUnicodeString(AbsoluteFileName);
78 return Status;
79 }
80
81 if (!CdfsFCBIsRoot(Fcb))
82 {
83 Status = RtlAppendUnicodeToString(AbsoluteFileName,
84 L"\\");
85 if (!NT_SUCCESS(Status))
86 {
87 RtlFreeUnicodeString(AbsoluteFileName);
88 return Status;
89 }
90 }
91
92 Status = RtlAppendUnicodeStringToString(AbsoluteFileName,
93 RelativeFileName);
94 if (!NT_SUCCESS(Status))
95 {
96 RtlFreeUnicodeString(AbsoluteFileName);
97 return Status;
98 }
99
100 return STATUS_SUCCESS;
101 }
102
103
104 /*
105 * FUNCTION: Opens a file
106 */
107 static NTSTATUS
108 CdfsOpenFile(PDEVICE_EXTENSION DeviceExt,
109 PFILE_OBJECT FileObject,
110 PUNICODE_STRING FileName)
111 {
112 PFCB ParentFcb;
113 PFCB Fcb;
114 NTSTATUS Status;
115 UNICODE_STRING AbsFileName;
116
117 DPRINT("CdfsOpenFile(%08lx, %08lx, %wZ)\n", DeviceExt, FileObject, FileName);
118
119 if (FileObject->RelatedFileObject)
120 {
121 DPRINT("Converting relative filename to absolute filename\n");
122
123 Status = CdfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
124 FileName,
125 &AbsFileName);
126 if (!NT_SUCCESS(Status))
127 {
128 return Status;
129 }
130
131 FileName = &AbsFileName;
132 }
133
134 Status = CdfsDeviceIoControl (DeviceExt->StorageDevice,
135 IOCTL_CDROM_CHECK_VERIFY,
136 NULL,
137 0,
138 NULL,
139 0,
140 FALSE);
141 DPRINT ("Status %lx\n", Status);
142 if (!NT_SUCCESS(Status))
143 {
144 if (Status == STATUS_NO_MEDIA_IN_DEVICE || Status == STATUS_VERIFY_REQUIRED)
145 {
146 DeviceExt->VolumeDevice->Flags |= DO_VERIFY_VOLUME;
147 }
148 DPRINT1 ("Status %lx\n", Status);
149 return Status;
150 }
151
152 DPRINT("PathName to open: %wZ\n", FileName);
153
154 /* try first to find an existing FCB in memory */
155 DPRINT("Checking for existing FCB in memory\n");
156 Fcb = CdfsGrabFCBFromTable(DeviceExt,
157 FileName);
158 if (Fcb == NULL)
159 {
160 DPRINT("No existing FCB found, making a new one if file exists.\n");
161 Status = CdfsGetFCBForFile(DeviceExt,
162 &ParentFcb,
163 &Fcb,
164 FileName);
165 if (ParentFcb != NULL)
166 {
167 CdfsReleaseFCB(DeviceExt,
168 ParentFcb);
169 }
170
171 if (!NT_SUCCESS (Status))
172 {
173 DPRINT("Could not make a new FCB, status: %x\n", Status);
174
175 if (FileName == &AbsFileName)
176 RtlFreeUnicodeString(&AbsFileName);
177
178 return Status;
179 }
180 }
181
182 DPRINT("Attaching FCB to fileObject\n");
183 Status = CdfsAttachFCBToFileObject(DeviceExt,
184 Fcb,
185 FileObject);
186
187 if ((FileName == &AbsFileName) && AbsFileName.Buffer)
188 ExFreePool(AbsFileName.Buffer);
189
190 return Status;
191 }
192
193
194 /*
195 * FUNCTION: Opens a file
196 */
197 static NTSTATUS
198 CdfsCreateFile(PDEVICE_OBJECT DeviceObject,
199 PIRP Irp)
200 {
201 PDEVICE_EXTENSION DeviceExt;
202 PIO_STACK_LOCATION Stack;
203 PFILE_OBJECT FileObject;
204 ULONG RequestedDisposition;
205 ULONG RequestedOptions;
206 PFCB Fcb;
207 NTSTATUS Status;
208
209 DPRINT("CdfsCreateFile() called\n");
210
211 DeviceExt = DeviceObject->DeviceExtension;
212 ASSERT(DeviceExt);
213 Stack = IoGetCurrentIrpStackLocation (Irp);
214 ASSERT(Stack);
215
216 RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
217 RequestedOptions = Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
218 DPRINT("RequestedDisposition %x, RequestedOptions %x\n",
219 RequestedDisposition, RequestedOptions);
220
221 FileObject = Stack->FileObject;
222
223 if (RequestedDisposition == FILE_CREATE ||
224 RequestedDisposition == FILE_OVERWRITE_IF ||
225 RequestedDisposition == FILE_SUPERSEDE)
226 {
227 return STATUS_ACCESS_DENIED;
228 }
229
230 Status = CdfsOpenFile(DeviceExt,
231 FileObject,
232 &FileObject->FileName);
233 if (NT_SUCCESS(Status))
234 {
235 Fcb = FileObject->FsContext;
236
237 /* Check whether the file has the requested attributes */
238 if (RequestedOptions & FILE_NON_DIRECTORY_FILE && CdfsFCBIsDirectory(Fcb))
239 {
240 CdfsCloseFile (DeviceExt, FileObject);
241 return STATUS_FILE_IS_A_DIRECTORY;
242 }
243
244 if (RequestedOptions & FILE_DIRECTORY_FILE && !CdfsFCBIsDirectory(Fcb))
245 {
246 CdfsCloseFile (DeviceExt, FileObject);
247 return STATUS_NOT_A_DIRECTORY;
248 }
249 }
250
251 /*
252 * If the directory containing the file to open doesn't exist then
253 * fail immediately
254 */
255 Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0;
256 Irp->IoStatus.Status = Status;
257
258 return Status;
259 }
260
261
262 NTSTATUS NTAPI
263 CdfsCreate(PDEVICE_OBJECT DeviceObject,
264 PIRP Irp)
265 {
266 PDEVICE_EXTENSION DeviceExt;
267 NTSTATUS Status;
268
269 if (DeviceObject == CdfsGlobalData->DeviceObject)
270 {
271 /* DeviceObject represents FileSystem instead of logical volume */
272 DPRINT("Opening file system\n");
273 Irp->IoStatus.Information = FILE_OPENED;
274 Status = STATUS_SUCCESS;
275 goto ByeBye;
276 }
277
278 DeviceExt = DeviceObject->DeviceExtension;
279
280 KeEnterCriticalRegion();
281 ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
282 TRUE);
283 Status = CdfsCreateFile(DeviceObject,
284 Irp);
285 ExReleaseResourceLite(&DeviceExt->DirResource);
286 KeLeaveCriticalRegion();
287
288 ByeBye:
289 Irp->IoStatus.Status = Status;
290 IoCompleteRequest(Irp,
291 NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT);
292
293 return Status;
294 }
295
296 /* EOF */