[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: 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->Length >= sizeof(WCHAR) &&
54 RelativeFileName->Buffer[0] == L'\\'))
55 {
56 return STATUS_INVALID_PARAMETER;
57 }
58
59 /* construct absolute path name */
60 Length = Fcb->PathName.Length +
61 sizeof(WCHAR) +
62 RelativeFileName->Length +
63 sizeof(WCHAR);
64 AbsoluteFileName->Length = 0;
65 AbsoluteFileName->MaximumLength = Length;
66 AbsoluteFileName->Buffer = ExAllocatePoolWithTag(NonPagedPool, Length, CDFS_FILENAME_TAG);
67 if (AbsoluteFileName->Buffer == NULL)
68 {
69 return STATUS_INSUFFICIENT_RESOURCES;
70 }
71
72 Status = RtlAppendUnicodeStringToString(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 DPRINT1 ("Status %lx\n", Status);
144 return Status;
145 }
146
147 DPRINT("PathName to open: %wZ\n", FileName);
148
149 /* try first to find an existing FCB in memory */
150 DPRINT("Checking for existing FCB in memory\n");
151 Fcb = CdfsGrabFCBFromTable(DeviceExt,
152 FileName);
153 if (Fcb == NULL)
154 {
155 DPRINT("No existing FCB found, making a new one if file exists.\n");
156 Status = CdfsGetFCBForFile(DeviceExt,
157 &ParentFcb,
158 &Fcb,
159 FileName);
160 if (ParentFcb != NULL)
161 {
162 CdfsReleaseFCB(DeviceExt,
163 ParentFcb);
164 }
165
166 if (!NT_SUCCESS (Status))
167 {
168 DPRINT("Could not make a new FCB, status: %x\n", Status);
169
170 if (FileName == &AbsFileName)
171 RtlFreeUnicodeString(&AbsFileName);
172
173 return Status;
174 }
175 }
176
177 DPRINT("Attaching FCB to fileObject\n");
178 Status = CdfsAttachFCBToFileObject(DeviceExt,
179 Fcb,
180 FileObject);
181
182 if ((FileName == &AbsFileName) && AbsFileName.Buffer)
183 ExFreePoolWithTag(AbsFileName.Buffer, CDFS_FILENAME_TAG);
184
185 return Status;
186 }
187
188
189 /*
190 * FUNCTION: Opens a file
191 */
192 static NTSTATUS
193 CdfsCreateFile(PDEVICE_OBJECT DeviceObject,
194 PIRP Irp)
195 {
196 PDEVICE_EXTENSION DeviceExt;
197 PIO_STACK_LOCATION Stack;
198 PFILE_OBJECT FileObject;
199 ULONG RequestedDisposition;
200 ULONG RequestedOptions;
201 PFCB Fcb;
202 NTSTATUS Status;
203
204 DPRINT("CdfsCreateFile() called\n");
205
206 DeviceExt = DeviceObject->DeviceExtension;
207 ASSERT(DeviceExt);
208 Stack = IoGetCurrentIrpStackLocation (Irp);
209 ASSERT(Stack);
210
211 RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
212 RequestedOptions = Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
213 DPRINT("RequestedDisposition %x, RequestedOptions %x\n",
214 RequestedDisposition, RequestedOptions);
215
216 FileObject = Stack->FileObject;
217
218 if (RequestedDisposition == FILE_CREATE ||
219 RequestedDisposition == FILE_OVERWRITE_IF ||
220 RequestedDisposition == FILE_SUPERSEDE)
221 {
222 return STATUS_ACCESS_DENIED;
223 }
224
225 Status = CdfsOpenFile(DeviceExt,
226 FileObject,
227 &FileObject->FileName);
228 if (NT_SUCCESS(Status))
229 {
230 Fcb = FileObject->FsContext;
231
232 /* Check whether the file has the requested attributes */
233 if (RequestedOptions & FILE_NON_DIRECTORY_FILE && CdfsFCBIsDirectory(Fcb))
234 {
235 CdfsCloseFile (DeviceExt, FileObject);
236 return STATUS_FILE_IS_A_DIRECTORY;
237 }
238
239 if (RequestedOptions & FILE_DIRECTORY_FILE && !CdfsFCBIsDirectory(Fcb))
240 {
241 CdfsCloseFile (DeviceExt, FileObject);
242 return STATUS_NOT_A_DIRECTORY;
243 }
244 }
245
246 /*
247 * If the directory containing the file to open doesn't exist then
248 * fail immediately
249 */
250 Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0;
251
252 return Status;
253 }
254
255
256 NTSTATUS NTAPI
257 CdfsCreate(
258 PCDFS_IRP_CONTEXT IrpContext)
259 {
260 PDEVICE_OBJECT DeviceObject;
261 PDEVICE_EXTENSION DeviceExt;
262 NTSTATUS Status;
263
264 DPRINT("CdfsCreate()\n");
265
266 ASSERT(IrpContext);
267
268 DeviceObject = IrpContext->DeviceObject;
269 if (DeviceObject == CdfsGlobalData->CdFsDeviceObject || DeviceObject == CdfsGlobalData->HddFsDeviceObject)
270 {
271 /* DeviceObject represents FileSystem instead of logical volume */
272 DPRINT("Opening file system\n");
273 IrpContext->Irp->IoStatus.Information = FILE_OPENED;
274 return STATUS_SUCCESS;
275 }
276
277 DeviceExt = DeviceObject->DeviceExtension;
278
279 KeEnterCriticalRegion();
280 ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
281 TRUE);
282 Status = CdfsCreateFile(DeviceObject,
283 IrpContext->Irp);
284 ExReleaseResourceLite(&DeviceExt->DirResource);
285 KeLeaveCriticalRegion();
286
287 return Status;
288 }
289
290 /* EOF */