branch update for HEAD-2003050101
[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
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       return(STATUS_UNSUCCESSFUL);
108     }
109
110   //FIXME: Get cannonical path name (remove .'s, ..'s and extra separators)
111
112   DPRINT("PathName to open: %S\n", FileName);
113
114   /*  try first to find an existing FCB in memory  */
115   DPRINT("Checking for existing FCB in memory\n");
116   Fcb = CdfsGrabFCBFromTable(DeviceExt,
117                              FileName);
118   if (Fcb == NULL)
119     {
120       DPRINT("No existing FCB found, making a new one if file exists.\n");
121       Status = CdfsGetFCBForFile(DeviceExt,
122                                  &ParentFcb,
123                                  &Fcb,
124                                  FileName);
125       if (ParentFcb != NULL)
126         {
127           CdfsReleaseFCB(DeviceExt,
128                          ParentFcb);
129         }
130
131       if (!NT_SUCCESS (Status))
132         {
133           DPRINT("Could not make a new FCB, status: %x\n", Status);
134
135           if (AbsFileName)
136             ExFreePool(AbsFileName);
137
138           return(Status);
139         }
140     }
141
142   DPRINT("Attaching FCB to fileObject\n");
143   Status = CdfsAttachFCBToFileObject(DeviceExt,
144                                      Fcb,
145                                      FileObject);
146
147   if (AbsFileName)
148     ExFreePool (AbsFileName);
149
150   return  Status;
151 }
152
153
154
155
156 static NTSTATUS
157 CdfsCreateFile(PDEVICE_OBJECT DeviceObject,
158                PIRP Irp)
159 /*
160  * FUNCTION: Opens a file
161  */
162 {
163   PDEVICE_EXTENSION DeviceExt;
164   PIO_STACK_LOCATION Stack;
165   PFILE_OBJECT FileObject;
166   ULONG RequestedDisposition;
167   ULONG RequestedOptions;
168   PFCB Fcb;
169 //  PWSTR FileName;
170   NTSTATUS Status;
171
172   DPRINT("CdfsCreateFile() called\n");
173
174   DeviceExt = DeviceObject->DeviceExtension;
175   assert (DeviceExt);
176   Stack = IoGetCurrentIrpStackLocation (Irp);
177   assert (Stack);
178
179   RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
180   RequestedOptions = Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
181   DPRINT("RequestedDisposition %x, RequestedOptions %x\n", 
182          RequestedDisposition, RequestedOptions);
183
184   FileObject = Stack->FileObject;
185
186   if (RequestedDisposition == FILE_CREATE ||
187       RequestedDisposition == FILE_OVERWRITE_IF ||
188       RequestedDisposition == FILE_SUPERSEDE)
189     {
190       return(STATUS_ACCESS_DENIED);
191     }
192
193   Status = CdfsOpenFile(DeviceExt,
194                         FileObject,
195                         FileObject->FileName.Buffer);
196
197   if (NT_SUCCESS(Status))
198   {
199     Fcb = FileObject->FsContext;
200     /*
201      * Check the file has the requested attributes
202      */
203     if (RequestedOptions & FILE_NON_DIRECTORY_FILE && CdfsFCBIsDirectory(Fcb))
204     {
205        CdfsCloseFile (DeviceExt, FileObject);
206        return STATUS_FILE_IS_A_DIRECTORY;
207     }
208     if (RequestedOptions & FILE_DIRECTORY_FILE && !CdfsFCBIsDirectory(Fcb))
209     {
210        CdfsCloseFile (DeviceExt, FileObject);
211        return STATUS_NOT_A_DIRECTORY;
212     }
213   }  
214
215   /*
216    * If the directory containing the file to open doesn't exist then
217    * fail immediately
218    */
219   Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0;
220   Irp->IoStatus.Status = Status;
221
222   return(Status);
223 }
224
225
226 NTSTATUS STDCALL
227 CdfsCreate(PDEVICE_OBJECT DeviceObject,
228            PIRP Irp)
229 {
230   PDEVICE_EXTENSION DeviceExt;
231   NTSTATUS Status;
232
233   if (DeviceObject == CdfsGlobalData->DeviceObject)
234     {
235       /* DeviceObject represents FileSystem instead of logical volume */
236       DPRINT("Opening file system\n");
237       Irp->IoStatus.Information = FILE_OPENED;
238       Status = STATUS_SUCCESS;
239       goto ByeBye;
240     }
241
242   DeviceExt = DeviceObject->DeviceExtension;
243
244   ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
245                                  TRUE);
246   Status = CdfsCreateFile(DeviceObject,
247                           Irp);
248   ExReleaseResourceLite(&DeviceExt->DirResource);
249
250 ByeBye:
251   Irp->IoStatus.Status = Status;
252   IoCompleteRequest(Irp,
253                     NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT);
254
255   return(Status);
256 }
257
258 /* EOF */