d0c8010742b5cd68faf04d97f18a7f0eef27e944
[reactos.git] / reactos / 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 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
22 * FILE: drivers/filesystems/cdfs/cdfs.c
23 * PURPOSE: CDROM (ISO 9660) filesystem driver
24 * PROGRAMMER: Art Yerkes
25 * Eric Kohl
26 */
27
28 /* INCLUDES *****************************************************************/
29
30 #include "cdfs.h"
31
32 #define NDEBUG
33 #include <debug.h>
34
35 /* FUNCTIONS ****************************************************************/
36
37 static NTSTATUS
38 CdfsMakeAbsoluteFilename(PFILE_OBJECT FileObject,
39 PUNICODE_STRING RelativeFileName,
40 PUNICODE_STRING AbsoluteFileName)
41 {
42 USHORT Length;
43 PFCB Fcb;
44 NTSTATUS Status;
45
46 DPRINT("try related for %wZ\n", RelativeFileName);
47 Fcb = FileObject->FsContext;
48 ASSERT(Fcb);
49
50 /* verify related object is a directory and target name
51 don't start with \. */
52 if ((Fcb->Entry.FileFlags & FILE_FLAG_DIRECTORY) == 0 ||
53 RelativeFileName->Buffer[0] == L'\\')
54 {
55 return STATUS_INVALID_PARAMETER;
56 }
57
58 /* construct absolute path name */
59 Length = Fcb->PathName.Length +
60 sizeof(WCHAR) +
61 RelativeFileName->Length +
62 sizeof(WCHAR);
63 AbsoluteFileName->Length = 0;
64 AbsoluteFileName->MaximumLength = Length;
65 AbsoluteFileName->Buffer = ExAllocatePoolWithTag(NonPagedPool, Length, CDFS_FILENAME_TAG);
66 if (AbsoluteFileName->Buffer == NULL)
67 {
68 return STATUS_INSUFFICIENT_RESOURCES;
69 }
70
71 Status = RtlAppendUnicodeStringToString(AbsoluteFileName,
72 &Fcb->PathName);
73 if (!NT_SUCCESS(Status))
74 {
75 RtlFreeUnicodeString(AbsoluteFileName);
76 return Status;
77 }
78
79 if (!CdfsFCBIsRoot(Fcb))
80 {
81 Status = RtlAppendUnicodeToString(AbsoluteFileName,
82 L"\\");
83 if (!NT_SUCCESS(Status))
84 {
85 RtlFreeUnicodeString(AbsoluteFileName);
86 return Status;
87 }
88 }
89
90 Status = RtlAppendUnicodeStringToString(AbsoluteFileName,
91 RelativeFileName);
92 if (!NT_SUCCESS(Status))
93 {
94 RtlFreeUnicodeString(AbsoluteFileName);
95 return Status;
96 }
97
98 return STATUS_SUCCESS;
99 }
100
101
102 /*
103 * FUNCTION: Opens a file
104 */
105 static NTSTATUS
106 CdfsOpenFile(PDEVICE_EXTENSION DeviceExt,
107 PFILE_OBJECT FileObject,
108 PUNICODE_STRING FileName)
109 {
110 PFCB ParentFcb;
111 PFCB Fcb;
112 NTSTATUS Status;
113 UNICODE_STRING AbsFileName;
114
115 DPRINT("CdfsOpenFile(%p, %p, %wZ)\n", DeviceExt, FileObject, FileName);
116
117 if (FileObject->RelatedFileObject)
118 {
119 DPRINT("Converting relative filename to absolute filename\n");
120
121 Status = CdfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
122 FileName,
123 &AbsFileName);
124 if (!NT_SUCCESS(Status))
125 {
126 return Status;
127 }
128
129 FileName = &AbsFileName;
130 }
131
132 Status = CdfsDeviceIoControl (DeviceExt->StorageDevice,
133 IOCTL_CDROM_CHECK_VERIFY,
134 NULL,
135 0,
136 NULL,
137 0,
138 FALSE);
139 DPRINT ("Status %lx\n", Status);
140 if (!NT_SUCCESS(Status))
141 {
142 DPRINT1 ("Status %lx\n", Status);
143 return Status;
144 }
145
146 DPRINT("PathName to open: %wZ\n", FileName);
147
148 /* try first to find an existing FCB in memory */
149 DPRINT("Checking for existing FCB in memory\n");
150 Fcb = CdfsGrabFCBFromTable(DeviceExt,
151 FileName);
152 if (Fcb == NULL)
153 {
154 DPRINT("No existing FCB found, making a new one if file exists.\n");
155 Status = CdfsGetFCBForFile(DeviceExt,
156 &ParentFcb,
157 &Fcb,
158 FileName);
159 if (ParentFcb != NULL)
160 {
161 CdfsReleaseFCB(DeviceExt,
162 ParentFcb);
163 }
164
165 if (!NT_SUCCESS (Status))
166 {
167 DPRINT("Could not make a new FCB, status: %x\n", Status);
168
169 if (FileName == &AbsFileName)
170 RtlFreeUnicodeString(&AbsFileName);
171
172 return Status;
173 }
174 }
175
176 DPRINT("Attaching FCB to fileObject\n");
177 Status = CdfsAttachFCBToFileObject(DeviceExt,
178 Fcb,
179 FileObject);
180
181 if ((FileName == &AbsFileName) && AbsFileName.Buffer)
182 ExFreePoolWithTag(AbsFileName.Buffer, CDFS_FILENAME_TAG);
183
184 return Status;
185 }
186
187
188 /*
189 * FUNCTION: Opens a file
190 */
191 static NTSTATUS
192 CdfsCreateFile(PDEVICE_OBJECT DeviceObject,
193 PIRP Irp)
194 {
195 PDEVICE_EXTENSION DeviceExt;
196 PIO_STACK_LOCATION Stack;
197 PFILE_OBJECT FileObject;
198 ULONG RequestedDisposition;
199 ULONG RequestedOptions;
200 PFCB Fcb;
201 NTSTATUS Status;
202
203 DPRINT("CdfsCreateFile() called\n");
204
205 DeviceExt = DeviceObject->DeviceExtension;
206 ASSERT(DeviceExt);
207 Stack = IoGetCurrentIrpStackLocation (Irp);
208 ASSERT(Stack);
209
210 RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
211 RequestedOptions = Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
212 DPRINT("RequestedDisposition %x, RequestedOptions %x\n",
213 RequestedDisposition, RequestedOptions);
214
215 FileObject = Stack->FileObject;
216
217 if (RequestedDisposition == FILE_CREATE ||
218 RequestedDisposition == FILE_OVERWRITE_IF ||
219 RequestedDisposition == FILE_SUPERSEDE)
220 {
221 return STATUS_ACCESS_DENIED;
222 }
223
224 Status = CdfsOpenFile(DeviceExt,
225 FileObject,
226 &FileObject->FileName);
227 if (NT_SUCCESS(Status))
228 {
229 Fcb = FileObject->FsContext;
230
231 /* Check whether the file has the requested attributes */
232 if (RequestedOptions & FILE_NON_DIRECTORY_FILE && CdfsFCBIsDirectory(Fcb))
233 {
234 CdfsCloseFile (DeviceExt, FileObject);
235 return STATUS_FILE_IS_A_DIRECTORY;
236 }
237
238 if (RequestedOptions & FILE_DIRECTORY_FILE && !CdfsFCBIsDirectory(Fcb))
239 {
240 CdfsCloseFile (DeviceExt, FileObject);
241 return STATUS_NOT_A_DIRECTORY;
242 }
243 }
244
245 /*
246 * If the directory containing the file to open doesn't exist then
247 * fail immediately
248 */
249 Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0;
250
251 return Status;
252 }
253
254
255 NTSTATUS NTAPI
256 CdfsCreate(
257 PCDFS_IRP_CONTEXT IrpContext)
258 {
259 PDEVICE_OBJECT DeviceObject;
260 PDEVICE_EXTENSION DeviceExt;
261 NTSTATUS Status;
262
263 DPRINT("CdfsCreate()\n");
264
265 ASSERT(IrpContext);
266
267 DeviceObject = IrpContext->DeviceObject;
268 if (DeviceObject == CdfsGlobalData->DeviceObject)
269 {
270 /* DeviceObject represents FileSystem instead of logical volume */
271 DPRINT("Opening file system\n");
272 IrpContext->Irp->IoStatus.Information = FILE_OPENED;
273 return STATUS_SUCCESS;
274 }
275
276 DeviceExt = DeviceObject->DeviceExtension;
277
278 KeEnterCriticalRegion();
279 ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
280 TRUE);
281 Status = CdfsCreateFile(DeviceObject,
282 IrpContext->Irp);
283 ExReleaseResourceLite(&DeviceExt->DirResource);
284 KeLeaveCriticalRegion();
285
286 return Status;
287 }
288
289 /* EOF */