- Use Unicode strings instead of WCHAR strings.
[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: create.c,v 1.12 2004/09/14 21:46:39 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 FileObject,
43 PUNICODE_STRING RelativeFileName,
44 PUNICODE_STRING AbsoluteFileName)
45 {
46 ULONG Length;
47 // PWSTR rcName;
48 PFCB Fcb;
49 NTSTATUS Status;
50
51 DPRINT("try related for %wZ\n", RelativeFileName);
52 Fcb = FileObject->FsContext;
53 assert(Fcb);
54
55 /* verify related object is a directory and target name
56 don't start with \. */
57 if ((Fcb->Entry.FileFlags & FILE_FLAG_DIRECTORY) == 0 ||
58 RelativeFileName->Buffer[0] == L'\\')
59 {
60 return STATUS_INVALID_PARAMETER;
61 }
62
63 /* construct absolute path name */
64 Length = (wcslen(Fcb->PathName) * sizeof(WCHAR)) +
65 sizeof(WCHAR) +
66 RelativeFileName->Length +
67 sizeof(WCHAR);
68 // assert(wcslen (Fcb->PathName) + 1 + wcslen (pRelativeFileName) + 1
69 // <= MAX_PATH);
70 // rcName = ExAllocatePool(NonPagedPool, MAX_PATH * sizeof(WCHAR));
71 // if (!rcName)
72 // {
73 // return(STATUS_INSUFFICIENT_RESOURCES);
74 // }
75 AbsoluteFileName->Length = 0;
76 AbsoluteFileName->MaximumLength = Length;
77 AbsoluteFileName->Buffer = ExAllocatePool(NonPagedPool,
78 Length);
79 if (AbsoluteFileName->Buffer == NULL)
80 {
81 CHECKPOINT1;
82 return STATUS_INSUFFICIENT_RESOURCES;
83 }
84
85
86 // wcscpy(rcName, Fcb->PathName);
87 Status = RtlAppendUnicodeToString(AbsoluteFileName,
88 Fcb->PathName);
89 if (!NT_SUCCESS(Status))
90 {
91 CHECKPOINT1;
92 RtlFreeUnicodeString(AbsoluteFileName);
93 return Status;
94 }
95
96 if (!CdfsFCBIsRoot(Fcb))
97 {
98 // wcscat (rcName, L"\\");
99 Status = RtlAppendUnicodeToString(AbsoluteFileName,
100 L"\\");
101 if (!NT_SUCCESS(Status))
102 {
103 CHECKPOINT1;
104 RtlFreeUnicodeString(AbsoluteFileName);
105 return Status;
106 }
107 }
108
109 Status = RtlAppendUnicodeStringToString(AbsoluteFileName,
110 RelativeFileName);
111 if (!NT_SUCCESS(Status))
112 {
113 CHECKPOINT1;
114 RtlFreeUnicodeString(AbsoluteFileName);
115 return Status;
116 }
117
118 // wcscat (rcName, pRelativeFileName);
119 // *pAbsoluteFilename = rcName;
120
121 return STATUS_SUCCESS;
122 }
123
124
125 /*
126 * FUNCTION: Opens a file
127 */
128 static NTSTATUS
129 CdfsOpenFile(PDEVICE_EXTENSION DeviceExt,
130 PFILE_OBJECT FileObject,
131 PUNICODE_STRING FileName)
132 {
133 PFCB ParentFcb;
134 PFCB Fcb;
135 NTSTATUS Status;
136 UNICODE_STRING AbsFileName;
137
138 DPRINT("CdfsOpenFile(%08lx, %08lx, %wZ)\n", DeviceExt, FileObject, FileName);
139
140 if (FileObject->RelatedFileObject)
141 {
142 DPRINT("Converting relative filename to absolute filename\n");
143
144 Status = CdfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
145 FileName,
146 &AbsFileName);
147 if (!NT_SUCCESS(Status))
148 {
149 return Status;
150 }
151
152 FileName = &AbsFileName;
153
154 RtlFreeUnicodeString(&AbsFileName);
155
156 return STATUS_UNSUCCESSFUL;
157 }
158
159 Status = CdfsDeviceIoControl (DeviceExt->StorageDevice,
160 IOCTL_CDROM_CHECK_VERIFY,
161 NULL,
162 0,
163 NULL,
164 0,
165 TRUE);
166 DPRINT ("Status %lx\n", Status);
167 if (Status == STATUS_VERIFY_REQUIRED)
168 {
169 PDEVICE_OBJECT DeviceToVerify;
170
171 DPRINT1 ("Media change detected!\n");
172 DPRINT1 ("Device %p\n", DeviceExt->VolumeDevice);
173
174 DeviceToVerify = IoGetDeviceToVerify (PsGetCurrentThread ());
175 IoSetDeviceToVerify (PsGetCurrentThread (),
176 NULL);
177
178 Status = IoVerifyVolume (DeviceToVerify,
179 FALSE);
180 if (!NT_SUCCESS(Status))
181 {
182 DPRINT1 ("Status %lx\n", Status);
183 return Status;
184 }
185 }
186 else if (!NT_SUCCESS(Status))
187 {
188 DPRINT1 ("Status %lx\n", Status);
189 return Status;
190 }
191
192 DPRINT("PathName to open: %wZ\n", FileName);
193
194 /* try first to find an existing FCB in memory */
195 DPRINT("Checking for existing FCB in memory\n");
196 Fcb = CdfsGrabFCBFromTable(DeviceExt,
197 FileName);
198 if (Fcb == NULL)
199 {
200 DPRINT("No existing FCB found, making a new one if file exists.\n");
201 Status = CdfsGetFCBForFile(DeviceExt,
202 &ParentFcb,
203 &Fcb,
204 FileName);
205 if (ParentFcb != NULL)
206 {
207 CdfsReleaseFCB(DeviceExt,
208 ParentFcb);
209 }
210
211 if (!NT_SUCCESS (Status))
212 {
213 DPRINT("Could not make a new FCB, status: %x\n", Status);
214
215 if (FileName == &AbsFileName)
216 RtlFreeUnicodeString(&AbsFileName);
217
218 return Status;
219 }
220 }
221
222 DPRINT("Attaching FCB to fileObject\n");
223 Status = CdfsAttachFCBToFileObject(DeviceExt,
224 Fcb,
225 FileObject);
226
227 if (FileName == &AbsFileName)
228 RtlFreeUnicodeString(&AbsFileName);
229
230 return Status;
231 }
232
233
234 /*
235 * FUNCTION: Opens a file
236 */
237 static NTSTATUS
238 CdfsCreateFile(PDEVICE_OBJECT DeviceObject,
239 PIRP Irp)
240 {
241 PDEVICE_EXTENSION DeviceExt;
242 PIO_STACK_LOCATION Stack;
243 PFILE_OBJECT FileObject;
244 ULONG RequestedDisposition;
245 ULONG RequestedOptions;
246 PFCB Fcb;
247 NTSTATUS Status;
248
249 DPRINT("CdfsCreateFile() called\n");
250
251 DeviceExt = DeviceObject->DeviceExtension;
252 assert (DeviceExt);
253 Stack = IoGetCurrentIrpStackLocation (Irp);
254 assert (Stack);
255
256 RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
257 RequestedOptions = Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
258 DPRINT("RequestedDisposition %x, RequestedOptions %x\n",
259 RequestedDisposition, RequestedOptions);
260
261 FileObject = Stack->FileObject;
262
263 if (RequestedDisposition == FILE_CREATE ||
264 RequestedDisposition == FILE_OVERWRITE_IF ||
265 RequestedDisposition == FILE_SUPERSEDE)
266 {
267 return STATUS_ACCESS_DENIED;
268 }
269
270 Status = CdfsOpenFile(DeviceExt,
271 FileObject,
272 &FileObject->FileName);
273 if (NT_SUCCESS(Status))
274 {
275 Fcb = FileObject->FsContext;
276
277 /* Check whether the file has the requested attributes */
278 if (RequestedOptions & FILE_NON_DIRECTORY_FILE && CdfsFCBIsDirectory(Fcb))
279 {
280 CdfsCloseFile (DeviceExt, FileObject);
281 return STATUS_FILE_IS_A_DIRECTORY;
282 }
283
284 if (RequestedOptions & FILE_DIRECTORY_FILE && !CdfsFCBIsDirectory(Fcb))
285 {
286 CdfsCloseFile (DeviceExt, FileObject);
287 return STATUS_NOT_A_DIRECTORY;
288 }
289 }
290
291 /*
292 * If the directory containing the file to open doesn't exist then
293 * fail immediately
294 */
295 Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0;
296 Irp->IoStatus.Status = Status;
297
298 return Status;
299 }
300
301
302 NTSTATUS STDCALL
303 CdfsCreate(PDEVICE_OBJECT DeviceObject,
304 PIRP Irp)
305 {
306 PDEVICE_EXTENSION DeviceExt;
307 NTSTATUS Status;
308
309 if (DeviceObject == CdfsGlobalData->DeviceObject)
310 {
311 /* DeviceObject represents FileSystem instead of logical volume */
312 DPRINT("Opening file system\n");
313 Irp->IoStatus.Information = FILE_OPENED;
314 Status = STATUS_SUCCESS;
315 goto ByeBye;
316 }
317
318 DeviceExt = DeviceObject->DeviceExtension;
319
320 ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
321 TRUE);
322 Status = CdfsCreateFile(DeviceObject,
323 Irp);
324 ExReleaseResourceLite(&DeviceExt->DirResource);
325
326 ByeBye:
327 Irp->IoStatus.Status = Status;
328 IoCompleteRequest(Irp,
329 NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT);
330
331 return Status;
332 }
333
334 /* EOF */