3a58787bd79884d941960d93510734844a813ae6
[reactos.git] / reactos / drivers / fs / cdfs / create.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2002, 2003 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: create.c,v 1.11 2003/11/13 15:25:08 ekohl Exp $
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 pFileObject,
43 PWSTR pRelativeFileName,
44 PWSTR *pAbsoluteFilename)
45 {
46 PWSTR rcName;
47 PFCB Fcb;
48
49 DPRINT("try related for %S\n", pRelativeFileName);
50 Fcb = pFileObject->FsContext;
51 assert(Fcb);
52
53 /* verify related object is a directory and target name
54 don't start with \. */
55 if ((Fcb->Entry.FileFlags & 0x02) == 0 ||
56 pRelativeFileName[0] == L'\\')
57 {
58 return(STATUS_INVALID_PARAMETER);
59 }
60
61 /* construct absolute path name */
62 assert(wcslen (Fcb->PathName) + 1 + wcslen (pRelativeFileName) + 1
63 <= MAX_PATH);
64 rcName = ExAllocatePool(NonPagedPool, MAX_PATH * sizeof(WCHAR));
65 if (!rcName)
66 {
67 return(STATUS_INSUFFICIENT_RESOURCES);
68 }
69
70 wcscpy(rcName, Fcb->PathName);
71 if (!CdfsFCBIsRoot(Fcb))
72 wcscat (rcName, L"\\");
73 wcscat (rcName, pRelativeFileName);
74 *pAbsoluteFilename = rcName;
75
76 return(STATUS_SUCCESS);
77 }
78
79
80 static NTSTATUS
81 CdfsOpenFile(PDEVICE_EXTENSION DeviceExt,
82 PFILE_OBJECT FileObject,
83 PWSTR FileName)
84 /*
85 * FUNCTION: Opens a file
86 */
87 {
88 PFCB ParentFcb;
89 PFCB Fcb;
90 NTSTATUS Status;
91 PWSTR AbsFileName = NULL;
92
93 DPRINT("CdfsOpenFile(%08lx, %08lx, %S)\n", DeviceExt, FileObject, FileName);
94
95 if (FileObject->RelatedFileObject)
96 {
97 DPRINT("Converting relative filename to absolute filename\n");
98
99 Status = CdfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
100 FileName,
101 &AbsFileName);
102 FileName = AbsFileName;
103 if (!NT_SUCCESS(Status))
104 {
105 return Status;
106 }
107
108 return STATUS_UNSUCCESSFUL;
109 }
110
111 Status = CdfsDeviceIoControl (DeviceExt->StorageDevice,
112 IOCTL_CDROM_CHECK_VERIFY,
113 NULL,
114 0,
115 NULL,
116 0,
117 TRUE);
118 DPRINT ("Status %lx\n", Status);
119 if (Status == STATUS_VERIFY_REQUIRED)
120 {
121 PDEVICE_OBJECT DeviceToVerify;
122
123 DPRINT1 ("Media change detected!\n");
124 DPRINT1 ("Device %p\n", DeviceExt->VolumeDevice);
125
126 DeviceToVerify = IoGetDeviceToVerify (PsGetCurrentThread ());
127 IoSetDeviceToVerify (PsGetCurrentThread (),
128 NULL);
129
130 Status = IoVerifyVolume (DeviceToVerify,
131 FALSE);
132 if (!NT_SUCCESS(Status))
133 {
134 DPRINT1 ("Status %lx\n", Status);
135 return Status;
136 }
137 }
138 else if (!NT_SUCCESS(Status))
139 {
140 DPRINT1 ("Status %lx\n", Status);
141 return Status;
142 }
143
144 //FIXME: Get cannonical path name (remove .'s, ..'s and extra separators)
145
146 DPRINT("PathName to open: %S\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 (AbsFileName)
170 ExFreePool(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 (AbsFileName)
182 ExFreePool (AbsFileName);
183
184 return Status;
185 }
186
187
188 static NTSTATUS
189 CdfsCreateFile(PDEVICE_OBJECT DeviceObject,
190 PIRP Irp)
191 /*
192 * FUNCTION: Opens a file
193 */
194 {
195 PDEVICE_EXTENSION DeviceExt;
196 PIO_STACK_LOCATION Stack;
197 PFILE_OBJECT FileObject;
198 ULONG RequestedDisposition;
199 ULONG RequestedOptions;
200 PFCB Fcb;
201 // PWSTR FileName;
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.Buffer);
228
229 if (NT_SUCCESS(Status))
230 {
231 Fcb = FileObject->FsContext;
232
233 /* Check whether the file has the requested attributes */
234 if (RequestedOptions & FILE_NON_DIRECTORY_FILE && CdfsFCBIsDirectory(Fcb))
235 {
236 CdfsCloseFile (DeviceExt, FileObject);
237 return STATUS_FILE_IS_A_DIRECTORY;
238 }
239
240 if (RequestedOptions & FILE_DIRECTORY_FILE && !CdfsFCBIsDirectory(Fcb))
241 {
242 CdfsCloseFile (DeviceExt, FileObject);
243 return STATUS_NOT_A_DIRECTORY;
244 }
245 }
246
247 /*
248 * If the directory containing the file to open doesn't exist then
249 * fail immediately
250 */
251 Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0;
252 Irp->IoStatus.Status = Status;
253
254 return Status;
255 }
256
257
258 NTSTATUS STDCALL
259 CdfsCreate(PDEVICE_OBJECT DeviceObject,
260 PIRP Irp)
261 {
262 PDEVICE_EXTENSION DeviceExt;
263 NTSTATUS Status;
264
265 if (DeviceObject == CdfsGlobalData->DeviceObject)
266 {
267 /* DeviceObject represents FileSystem instead of logical volume */
268 DPRINT("Opening file system\n");
269 Irp->IoStatus.Information = FILE_OPENED;
270 Status = STATUS_SUCCESS;
271 goto ByeBye;
272 }
273
274 DeviceExt = DeviceObject->DeviceExtension;
275
276 ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
277 TRUE);
278 Status = CdfsCreateFile(DeviceObject,
279 Irp);
280 ExReleaseResourceLite(&DeviceExt->DirResource);
281
282 ByeBye:
283 Irp->IoStatus.Status = Status;
284 IoCompleteRequest(Irp,
285 NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT);
286
287 return Status;
288 }
289
290 /* EOF */