xref: /reactos/drivers/filesystems/cdfs/create.c (revision 595b846d)
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         DeviceExt->OpenHandleCount++;
246     }
247 
248     /*
249     * If the directory containing the file to open doesn't exist then
250     * fail immediately
251     */
252     Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0;
253 
254     return Status;
255 }
256 
257 
258 NTSTATUS NTAPI
259 CdfsCreate(
260     PCDFS_IRP_CONTEXT IrpContext)
261 {
262     PDEVICE_OBJECT DeviceObject;
263     PDEVICE_EXTENSION DeviceExt;
264     NTSTATUS Status;
265 
266     DPRINT("CdfsCreate()\n");
267 
268     ASSERT(IrpContext);
269 
270     DeviceObject = IrpContext->DeviceObject;
271     DeviceExt = DeviceObject->DeviceExtension;
272     if (BooleanFlagOn(DeviceExt->Flags, VCB_VOLUME_LOCKED))
273     {
274         return STATUS_ACCESS_DENIED;
275     }
276 
277     if (DeviceObject == CdfsGlobalData->CdFsDeviceObject || DeviceObject == CdfsGlobalData->HddFsDeviceObject)
278     {
279         /* DeviceObject represents FileSystem instead of logical volume */
280         DPRINT("Opening file system\n");
281         IrpContext->Irp->IoStatus.Information = FILE_OPENED;
282         DeviceExt->OpenHandleCount++;
283         return STATUS_SUCCESS;
284     }
285 
286     KeEnterCriticalRegion();
287     ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
288         TRUE);
289     Status = CdfsCreateFile(DeviceObject,
290                             IrpContext->Irp);
291     ExReleaseResourceLite(&DeviceExt->DirResource);
292     KeLeaveCriticalRegion();
293 
294     return Status;
295 }
296 
297 /* EOF */
298