:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / fs / ntfs / 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/ntfs/create.c
24  * PURPOSE:          NTFS filesystem driver
25  * PROGRAMMER:       Eric Kohl
26  */
27
28 /* INCLUDES *****************************************************************/
29
30 #include <ddk/ntddk.h>
31
32 //#define NDEBUG
33 #include <debug.h>
34
35 #include "ntfs.h"
36
37
38 /* FUNCTIONS ****************************************************************/
39
40 static NTSTATUS
41 NtfsMakeAbsoluteFilename(PFILE_OBJECT pFileObject,
42                          PWSTR pRelativeFileName,
43                          PWSTR *pAbsoluteFilename)
44 {
45   PWSTR rcName;
46   PFCB Fcb;
47   PCCB Ccb;
48
49   DPRINT("try related for %S\n", pRelativeFileName);
50   Ccb = pFileObject->FsContext2;
51   assert(Ccb);
52   Fcb = Ccb->Fcb;
53   assert(Fcb);
54
55   /* verify related object is a directory and target name
56      don't start with \. */
57   if (NtfsFCBIsDirectory(Fcb) == FALSE ||
58       pRelativeFileName[0] == L'\\')
59     {
60       return(STATUS_INVALID_PARAMETER);
61     }
62
63   /* construct absolute path name */
64   assert(wcslen (Fcb->PathName) + 1 + wcslen (pRelativeFileName) + 1
65           <= MAX_PATH);
66   rcName = ExAllocatePool(NonPagedPool, MAX_PATH * sizeof(WCHAR));
67   if (!rcName)
68     {
69       return(STATUS_INSUFFICIENT_RESOURCES);
70     }
71
72   wcscpy(rcName, Fcb->PathName);
73   if (!NtfsFCBIsRoot(Fcb))
74     wcscat (rcName, L"\\");
75   wcscat (rcName, pRelativeFileName);
76   *pAbsoluteFilename = rcName;
77
78   return(STATUS_SUCCESS);
79 }
80
81
82 static NTSTATUS
83 NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
84              PFILE_OBJECT FileObject,
85              PWSTR FileName)
86 /*
87  * FUNCTION: Opens a file
88  */
89 {
90   PFCB ParentFcb;
91   PFCB Fcb;
92   NTSTATUS Status;
93   PWSTR AbsFileName = NULL;
94
95   DPRINT("NtfsOpenFile(%08lx, %08lx, %S)\n", DeviceExt, FileObject, FileName);
96
97   if (FileObject->RelatedFileObject)
98     {
99       DPRINT("Converting relative filename to absolute filename\n");
100
101       Status = NtfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
102                                         FileName,
103                                         &AbsFileName);
104       FileName = AbsFileName;
105       if (!NT_SUCCESS(Status))
106         {
107           return(Status);
108         }
109       return(STATUS_UNSUCCESSFUL);
110     }
111
112   //FIXME: Get cannonical path name (remove .'s, ..'s and extra separators)
113
114   DPRINT("PathName to open: %S\n", FileName);
115
116   /*  try first to find an existing FCB in memory  */
117   DPRINT("Checking for existing FCB in memory\n");
118   Fcb = NtfsGrabFCBFromTable(DeviceExt,
119                              FileName);
120   if (Fcb == NULL)
121     {
122       DPRINT("No existing FCB found, making a new one if file exists.\n");
123       Status = NtfsGetFCBForFile(DeviceExt,
124                                  &ParentFcb,
125                                  &Fcb,
126                                  FileName);
127       if (ParentFcb != NULL)
128         {
129           NtfsReleaseFCB(DeviceExt,
130                          ParentFcb);
131         }
132
133       if (!NT_SUCCESS (Status))
134         {
135           DPRINT("Could not make a new FCB, status: %x\n", Status);
136
137           if (AbsFileName)
138             ExFreePool(AbsFileName);
139
140           return(Status);
141         }
142     }
143
144   DPRINT("Attaching FCB to fileObject\n");
145   Status = NtfsAttachFCBToFileObject(DeviceExt,
146                                      Fcb,
147                                      FileObject);
148
149   if (AbsFileName)
150     ExFreePool (AbsFileName);
151
152   return(Status);
153 }
154
155
156 static NTSTATUS
157 NtfsCreateFile(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("NtfsCreateFile() 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 =
181 //    Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
182 //  PagingFileCreate = (Stack->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE;
183 //  if ((RequestedOptions & FILE_DIRECTORY_FILE)
184 //      && RequestedDisposition == FILE_SUPERSEDE)
185 //    return STATUS_INVALID_PARAMETER;
186
187   FileObject = Stack->FileObject;
188
189   if (RequestedDisposition == FILE_CREATE ||
190       RequestedDisposition == FILE_OVERWRITE_IF ||
191       RequestedDisposition == FILE_SUPERSEDE)
192     {
193       return(STATUS_ACCESS_DENIED);
194     }
195
196   Status = NtfsOpenFile(DeviceExt,
197                         FileObject,
198                         FileObject->FileName.Buffer);
199
200   /*
201    * If the directory containing the file to open doesn't exist then
202    * fail immediately
203    */
204   Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0;
205   Irp->IoStatus.Status = Status;
206
207   return(Status);
208 }
209
210
211 NTSTATUS STDCALL
212 NtfsCreate(PDEVICE_OBJECT DeviceObject,
213            PIRP Irp)
214 {
215   PDEVICE_EXTENSION DeviceExt;
216   NTSTATUS Status;
217
218   if (DeviceObject == NtfsGlobalData->DeviceObject)
219     {
220       /* DeviceObject represents FileSystem instead of logical volume */
221       DPRINT("Opening file system\n");
222       Irp->IoStatus.Information = FILE_OPENED;
223       Status = STATUS_SUCCESS;
224       goto ByeBye;
225     }
226
227   DeviceExt = DeviceObject->DeviceExtension;
228
229   ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
230                                  TRUE);
231   Status = NtfsCreateFile(DeviceObject,
232                           Irp);
233   ExReleaseResourceLite(&DeviceExt->DirResource);
234
235 ByeBye:
236   Irp->IoStatus.Status = Status;
237   IoCompleteRequest(Irp,
238                     NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT);
239
240   return(Status);
241 }
242
243 /* EOF */