:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / fs / cdfs / create.c
1 /*
2  *  ReactOS kernel
3  *  Copyright (C) 2002 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  * UPDATE HISTORY: 
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   PCCB Ccb;
49
50   DPRINT("try related for %S\n", pRelativeFileName);
51   Ccb = pFileObject->FsContext2;
52   assert(Ccb);
53   Fcb = Ccb->Fcb;
54   assert(Fcb);
55
56   /* verify related object is a directory and target name
57      don't start with \. */
58   if (Fcb->Entry.FileFlags & 0x02 == 0 ||
59       pRelativeFileName[0] == L'\\')
60     {
61       return(STATUS_INVALID_PARAMETER);
62     }
63
64   /* construct absolute path name */
65   assert(wcslen (Fcb->PathName) + 1 + wcslen (pRelativeFileName) + 1
66           <= MAX_PATH);
67   rcName = ExAllocatePool(NonPagedPool, MAX_PATH * sizeof(WCHAR));
68   if (!rcName)
69     {
70       return(STATUS_INSUFFICIENT_RESOURCES);
71     }
72
73   wcscpy(rcName, Fcb->PathName);
74   if (!CdfsFCBIsRoot(Fcb))
75     wcscat (rcName, L"\\");
76   wcscat (rcName, pRelativeFileName);
77   *pAbsoluteFilename = rcName;
78
79   return(STATUS_SUCCESS);
80 }
81
82
83 static NTSTATUS
84 CdfsOpenFile(PDEVICE_EXTENSION DeviceExt,
85              PFILE_OBJECT FileObject,
86              PWSTR FileName)
87 /*
88  * FUNCTION: Opens a file
89  */
90 {
91   PFCB ParentFcb;
92   PFCB Fcb;
93   NTSTATUS Status;
94   PWSTR AbsFileName = NULL;
95
96   DPRINT("CdfsOpenFile(%08lx, %08lx, %S)\n", DeviceExt, FileObject, FileName);
97
98   if (FileObject->RelatedFileObject)
99     {
100       DPRINT("Converting relative filename to absolute filename\n");
101
102       Status = CdfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
103                                         FileName,
104                                         &AbsFileName);
105       FileName = AbsFileName;
106       if (!NT_SUCCESS(Status))
107         {
108           return(Status);
109         }
110       return(STATUS_UNSUCCESSFUL);
111     }
112
113   //FIXME: Get cannonical path name (remove .'s, ..'s and extra separators)
114
115   DPRINT("PathName to open: %S\n", FileName);
116
117   /*  try first to find an existing FCB in memory  */
118   DPRINT("Checking for existing FCB in memory\n");
119   Fcb = CdfsGrabFCBFromTable(DeviceExt,
120                              FileName);
121   if (Fcb == NULL)
122     {
123       DPRINT("No existing FCB found, making a new one if file exists.\n");
124       Status = CdfsGetFCBForFile(DeviceExt,
125                                  &ParentFcb,
126                                  &Fcb,
127                                  FileName);
128       if (ParentFcb != NULL)
129         {
130           CdfsReleaseFCB(DeviceExt,
131                          ParentFcb);
132         }
133
134       if (!NT_SUCCESS (Status))
135         {
136           DPRINT("Could not make a new FCB, status: %x\n", Status);
137
138           if (AbsFileName)
139             ExFreePool(AbsFileName);
140
141           return(Status);
142         }
143     }
144
145   DPRINT("Attaching FCB to fileObject\n");
146   Status = CdfsAttachFCBToFileObject(DeviceExt,
147                                      Fcb,
148                                      FileObject);
149
150   if (AbsFileName)
151     ExFreePool (AbsFileName);
152
153   return  Status;
154 }
155
156
157
158
159 static NTSTATUS
160 CdfsCreateFile(PDEVICE_OBJECT DeviceObject,
161                PIRP Irp)
162 /*
163  * FUNCTION: Opens a file
164  */
165 {
166   PDEVICE_EXTENSION DeviceExt;
167   PIO_STACK_LOCATION Stack;
168   PFILE_OBJECT FileObject;
169   ULONG RequestedDisposition;
170   ULONG RequestedOptions;
171   PFCB Fcb;
172   PCCB Ccb;
173 //  PWSTR FileName;
174   NTSTATUS Status;
175
176   DPRINT("CdfsCreateFile() called\n");
177
178   DeviceExt = DeviceObject->DeviceExtension;
179   assert (DeviceExt);
180   Stack = IoGetCurrentIrpStackLocation (Irp);
181   assert (Stack);
182
183   RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
184   RequestedOptions = Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
185   DPRINT("RequestedDisposition %x, RequestedOptions %x\n", 
186          RequestedDisposition, RequestedOptions);
187
188   FileObject = Stack->FileObject;
189
190   if (RequestedDisposition == FILE_CREATE ||
191       RequestedDisposition == FILE_OVERWRITE_IF ||
192       RequestedDisposition == FILE_SUPERSEDE)
193     {
194       return(STATUS_ACCESS_DENIED);
195     }
196
197   Status = CdfsOpenFile(DeviceExt,
198                         FileObject,
199                         FileObject->FileName.Buffer);
200
201   if (NT_SUCCESS(Status))
202   {
203     Ccb = FileObject->FsContext2;
204     Fcb = Ccb->Fcb;
205     /*
206      * Check the file has the requested attributes
207      */
208     if (RequestedOptions & FILE_NON_DIRECTORY_FILE && CdfsFCBIsDirectory(Fcb))
209     {
210        CdfsCloseFile (DeviceExt, FileObject);
211        return STATUS_FILE_IS_A_DIRECTORY;
212     }
213     if (RequestedOptions & FILE_DIRECTORY_FILE && !CdfsFCBIsDirectory(Fcb))
214     {
215        CdfsCloseFile (DeviceExt, FileObject);
216        return STATUS_NOT_A_DIRECTORY;
217     }
218   }  
219
220   /*
221    * If the directory containing the file to open doesn't exist then
222    * fail immediately
223    */
224   Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0;
225   Irp->IoStatus.Status = Status;
226
227   return(Status);
228 }
229
230
231 NTSTATUS STDCALL
232 CdfsCreate(PDEVICE_OBJECT DeviceObject,
233            PIRP Irp)
234 {
235   PDEVICE_EXTENSION DeviceExt;
236   NTSTATUS Status;
237
238   if (DeviceObject == CdfsGlobalData->DeviceObject)
239     {
240       /* DeviceObject represents FileSystem instead of logical volume */
241       DPRINT("Opening file system\n");
242       Irp->IoStatus.Information = FILE_OPENED;
243       Status = STATUS_SUCCESS;
244       goto ByeBye;
245     }
246
247   DeviceExt = DeviceObject->DeviceExtension;
248
249   ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
250                                  TRUE);
251   Status = CdfsCreateFile(DeviceObject,
252                           Irp);
253   ExReleaseResourceLite(&DeviceExt->DirResource);
254
255 ByeBye:
256   Irp->IoStatus.Status = Status;
257   IoCompleteRequest(Irp,
258                     NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT);
259
260   return(Status);
261 }
262
263 /* EOF */