[CDFS]
[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: services/fs/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 = (wcslen(Fcb->PathName) * sizeof(WCHAR)) +
60 sizeof(WCHAR) +
61 RelativeFileName->Length +
62 sizeof(WCHAR);
63 AbsoluteFileName->Length = 0;
64 AbsoluteFileName->MaximumLength = Length;
65 AbsoluteFileName->Buffer = ExAllocatePool(NonPagedPool,
66 Length);
67 if (AbsoluteFileName->Buffer == NULL)
68 {
69 return STATUS_INSUFFICIENT_RESOURCES;
70 }
71
72 Status = RtlAppendUnicodeToString(AbsoluteFileName,
73 Fcb->PathName);
74 if (!NT_SUCCESS(Status))
75 {
76 RtlFreeUnicodeString(AbsoluteFileName);
77 return Status;
78 }
79
80 if (!CdfsFCBIsRoot(Fcb))
81 {
82 Status = RtlAppendUnicodeToString(AbsoluteFileName,
83 L"\\");
84 if (!NT_SUCCESS(Status))
85 {
86 RtlFreeUnicodeString(AbsoluteFileName);
87 return Status;
88 }
89 }
90
91 Status = RtlAppendUnicodeStringToString(AbsoluteFileName,
92 RelativeFileName);
93 if (!NT_SUCCESS(Status))
94 {
95 RtlFreeUnicodeString(AbsoluteFileName);
96 return Status;
97 }
98
99 return STATUS_SUCCESS;
100 }
101
102
103 /*
104 * FUNCTION: Opens a file
105 */
106 static NTSTATUS
107 CdfsOpenFile(PDEVICE_EXTENSION DeviceExt,
108 PFILE_OBJECT FileObject,
109 PUNICODE_STRING FileName)
110 {
111 PFCB ParentFcb;
112 PFCB Fcb;
113 NTSTATUS Status;
114 UNICODE_STRING AbsFileName;
115
116 DPRINT("CdfsOpenFile(%p, %p, %wZ)\n", DeviceExt, FileObject, FileName);
117
118 if (FileObject->RelatedFileObject)
119 {
120 DPRINT("Converting relative filename to absolute filename\n");
121
122 Status = CdfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
123 FileName,
124 &AbsFileName);
125 if (!NT_SUCCESS(Status))
126 {
127 return Status;
128 }
129
130 FileName = &AbsFileName;
131 }
132
133 Status = CdfsDeviceIoControl (DeviceExt->StorageDevice,
134 IOCTL_CDROM_CHECK_VERIFY,
135 NULL,
136 0,
137 NULL,
138 0,
139 FALSE);
140 DPRINT ("Status %lx\n", Status);
141 if (!NT_SUCCESS(Status))
142 {
143 if (Status == STATUS_NO_MEDIA_IN_DEVICE || Status == STATUS_VERIFY_REQUIRED)
144 {
145 DeviceExt->VolumeDevice->Flags |= DO_VERIFY_VOLUME;
146 }
147 DPRINT1 ("Status %lx\n", Status);
148 return Status;
149 }
150
151 DPRINT("PathName to open: %wZ\n", FileName);
152
153 /* try first to find an existing FCB in memory */
154 DPRINT("Checking for existing FCB in memory\n");
155 Fcb = CdfsGrabFCBFromTable(DeviceExt,
156 FileName);
157 if (Fcb == NULL)
158 {
159 DPRINT("No existing FCB found, making a new one if file exists.\n");
160 Status = CdfsGetFCBForFile(DeviceExt,
161 &ParentFcb,
162 &Fcb,
163 FileName);
164 if (ParentFcb != NULL)
165 {
166 CdfsReleaseFCB(DeviceExt,
167 ParentFcb);
168 }
169
170 if (!NT_SUCCESS (Status))
171 {
172 DPRINT("Could not make a new FCB, status: %x\n", Status);
173
174 if (FileName == &AbsFileName)
175 RtlFreeUnicodeString(&AbsFileName);
176
177 return Status;
178 }
179 }
180
181 DPRINT("Attaching FCB to fileObject\n");
182 Status = CdfsAttachFCBToFileObject(DeviceExt,
183 Fcb,
184 FileObject);
185
186 if ((FileName == &AbsFileName) && AbsFileName.Buffer)
187 ExFreePool(AbsFileName.Buffer);
188
189 return Status;
190 }
191
192
193 /*
194 * FUNCTION: Opens a file
195 */
196 static NTSTATUS
197 CdfsCreateFile(PDEVICE_OBJECT DeviceObject,
198 PIRP Irp)
199 {
200 PDEVICE_EXTENSION DeviceExt;
201 PIO_STACK_LOCATION Stack;
202 PFILE_OBJECT FileObject;
203 ULONG RequestedDisposition;
204 ULONG RequestedOptions;
205 PFCB Fcb;
206 NTSTATUS Status;
207
208 DPRINT("CdfsCreateFile() called\n");
209
210 DeviceExt = DeviceObject->DeviceExtension;
211 ASSERT(DeviceExt);
212 Stack = IoGetCurrentIrpStackLocation (Irp);
213 ASSERT(Stack);
214
215 RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
216 RequestedOptions = Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
217 DPRINT("RequestedDisposition %x, RequestedOptions %x\n",
218 RequestedDisposition, RequestedOptions);
219
220 FileObject = Stack->FileObject;
221
222 if (RequestedDisposition == FILE_CREATE ||
223 RequestedDisposition == FILE_OVERWRITE_IF ||
224 RequestedDisposition == FILE_SUPERSEDE)
225 {
226 return STATUS_ACCESS_DENIED;
227 }
228
229 Status = CdfsOpenFile(DeviceExt,
230 FileObject,
231 &FileObject->FileName);
232 if (NT_SUCCESS(Status))
233 {
234 Fcb = FileObject->FsContext;
235
236 /* Check whether the file has the requested attributes */
237 if (RequestedOptions & FILE_NON_DIRECTORY_FILE && CdfsFCBIsDirectory(Fcb))
238 {
239 CdfsCloseFile (DeviceExt, FileObject);
240 return STATUS_FILE_IS_A_DIRECTORY;
241 }
242
243 if (RequestedOptions & FILE_DIRECTORY_FILE && !CdfsFCBIsDirectory(Fcb))
244 {
245 CdfsCloseFile (DeviceExt, FileObject);
246 return STATUS_NOT_A_DIRECTORY;
247 }
248 }
249
250 /*
251 * If the directory containing the file to open doesn't exist then
252 * fail immediately
253 */
254 Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0;
255 Irp->IoStatus.Status = Status;
256
257 return Status;
258 }
259
260
261 NTSTATUS NTAPI
262 CdfsCreate(PDEVICE_OBJECT DeviceObject,
263 PIRP Irp)
264 {
265 PDEVICE_EXTENSION DeviceExt;
266 NTSTATUS Status;
267
268 if (DeviceObject == CdfsGlobalData->DeviceObject)
269 {
270 /* DeviceObject represents FileSystem instead of logical volume */
271 DPRINT("Opening file system\n");
272 Irp->IoStatus.Information = FILE_OPENED;
273 Status = STATUS_SUCCESS;
274 goto ByeBye;
275 }
276
277 DeviceExt = DeviceObject->DeviceExtension;
278
279 KeEnterCriticalRegion();
280 ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
281 TRUE);
282 Status = CdfsCreateFile(DeviceObject,
283 Irp);
284 ExReleaseResourceLite(&DeviceExt->DirResource);
285 KeLeaveCriticalRegion();
286
287 ByeBye:
288 Irp->IoStatus.Status = Status;
289 IoCompleteRequest(Irp,
290 NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT);
291
292 return Status;
293 }
294
295 /* EOF */