tinus <o112w8r02@sneakemail.com>
[reactos.git] / reactos / drivers / fs / 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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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 <ddk/ntddk.h>
32
33 #define NDEBUG
34 #include <debug.h>
35
36 #include "cdfs.h"
37
38
39 /* FUNCTIONS ****************************************************************/
40
41 static NTSTATUS
42 CdfsMakeAbsoluteFilename(PFILE_OBJECT FileObject,
43 PUNICODE_STRING RelativeFileName,
44 PUNICODE_STRING AbsoluteFileName)
45 {
46 ULONG Length;
47 PFCB Fcb;
48 NTSTATUS Status;
49
50 DPRINT("try related for %wZ\n", RelativeFileName);
51 Fcb = FileObject->FsContext;
52 ASSERT(Fcb);
53
54 /* verify related object is a directory and target name
55 don't start with \. */
56 if ((Fcb->Entry.FileFlags & FILE_FLAG_DIRECTORY) == 0 ||
57 RelativeFileName->Buffer[0] == L'\\')
58 {
59 return STATUS_INVALID_PARAMETER;
60 }
61
62 /* construct absolute path name */
63 Length = (wcslen(Fcb->PathName) * sizeof(WCHAR)) +
64 sizeof(WCHAR) +
65 RelativeFileName->Length +
66 sizeof(WCHAR);
67 AbsoluteFileName->Length = 0;
68 AbsoluteFileName->MaximumLength = Length;
69 AbsoluteFileName->Buffer = ExAllocatePool(NonPagedPool,
70 Length);
71 if (AbsoluteFileName->Buffer == NULL)
72 {
73 return STATUS_INSUFFICIENT_RESOURCES;
74 }
75
76 Status = RtlAppendUnicodeToString(AbsoluteFileName,
77 Fcb->PathName);
78 if (!NT_SUCCESS(Status))
79 {
80 RtlFreeUnicodeString(AbsoluteFileName);
81 return Status;
82 }
83
84 if (!CdfsFCBIsRoot(Fcb))
85 {
86 Status = RtlAppendUnicodeToString(AbsoluteFileName,
87 L"\\");
88 if (!NT_SUCCESS(Status))
89 {
90 RtlFreeUnicodeString(AbsoluteFileName);
91 return Status;
92 }
93 }
94
95 Status = RtlAppendUnicodeStringToString(AbsoluteFileName,
96 RelativeFileName);
97 if (!NT_SUCCESS(Status))
98 {
99 RtlFreeUnicodeString(AbsoluteFileName);
100 return Status;
101 }
102
103 return STATUS_SUCCESS;
104 }
105
106
107 /*
108 * FUNCTION: Opens a file
109 */
110 static NTSTATUS
111 CdfsOpenFile(PDEVICE_EXTENSION DeviceExt,
112 PFILE_OBJECT FileObject,
113 PUNICODE_STRING FileName)
114 {
115 PFCB ParentFcb;
116 PFCB Fcb;
117 NTSTATUS Status;
118 UNICODE_STRING AbsFileName;
119
120 DPRINT("CdfsOpenFile(%08lx, %08lx, %wZ)\n", DeviceExt, FileObject, FileName);
121
122 if (FileObject->RelatedFileObject)
123 {
124 DPRINT("Converting relative filename to absolute filename\n");
125
126 Status = CdfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
127 FileName,
128 &AbsFileName);
129 if (!NT_SUCCESS(Status))
130 {
131 return Status;
132 }
133
134 FileName = &AbsFileName;
135 }
136
137 Status = CdfsDeviceIoControl (DeviceExt->StorageDevice,
138 IOCTL_CDROM_CHECK_VERIFY,
139 NULL,
140 0,
141 NULL,
142 0,
143 FALSE);
144 DPRINT ("Status %lx\n", Status);
145 if (!NT_SUCCESS(Status))
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 STDCALL
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 ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
280 TRUE);
281 Status = CdfsCreateFile(DeviceObject,
282 Irp);
283 ExReleaseResourceLite(&DeviceExt->DirResource);
284
285 ByeBye:
286 Irp->IoStatus.Status = Status;
287 IoCompleteRequest(Irp,
288 NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT);
289
290 return Status;
291 }
292
293 /* EOF */