[NTFS]
[reactos.git] / reactos / drivers / filesystems / 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19 * COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS kernel
21 * FILE: drivers/filesystem/ntfs/create.c
22 * PURPOSE: NTFS filesystem driver
23 * PROGRAMMER: Eric Kohl
24 */
25
26 /* INCLUDES *****************************************************************/
27
28 #include "ntfs.h"
29
30 #define NDEBUG
31 #include <debug.h>
32
33 /* FUNCTIONS ****************************************************************/
34
35 static
36 NTSTATUS
37 NtfsMakeAbsoluteFilename(PFILE_OBJECT pFileObject,
38 PWSTR pRelativeFileName,
39 PWSTR *pAbsoluteFilename)
40 {
41 PWSTR rcName;
42 PNTFS_FCB Fcb;
43
44 DPRINT("try related for %S\n", pRelativeFileName);
45 Fcb = pFileObject->FsContext;
46 ASSERT(Fcb);
47
48 /* verify related object is a directory and target name
49 don't start with \. */
50 if (NtfsFCBIsDirectory(Fcb) == FALSE ||
51 pRelativeFileName[0] == L'\\')
52 {
53 return STATUS_INVALID_PARAMETER;
54 }
55
56 /* construct absolute path name */
57 ASSERT(wcslen (Fcb->PathName) + 1 + wcslen (pRelativeFileName) + 1 <= MAX_PATH);
58 rcName = ExAllocatePoolWithTag(NonPagedPool, MAX_PATH * sizeof(WCHAR), TAG_NTFS);
59 if (!rcName)
60 {
61 return STATUS_INSUFFICIENT_RESOURCES;
62 }
63
64 wcscpy(rcName, Fcb->PathName);
65 if (!NtfsFCBIsRoot(Fcb))
66 wcscat (rcName, L"\\");
67 wcscat (rcName, pRelativeFileName);
68 *pAbsoluteFilename = rcName;
69
70 return STATUS_SUCCESS;
71 }
72
73
74 /*
75 * FUNCTION: Opens a file
76 */
77 static
78 NTSTATUS
79 NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
80 PFILE_OBJECT FileObject,
81 PWSTR FileName,
82 PNTFS_FCB * FoundFCB)
83 {
84 PNTFS_FCB ParentFcb;
85 PNTFS_FCB Fcb;
86 NTSTATUS Status;
87 PWSTR AbsFileName = NULL;
88
89 DPRINT1("NtfsOpenFile(%p, %p, %S, %p)\n", DeviceExt, FileObject, FileName, FoundFCB);
90
91 *FoundFCB = NULL;
92
93 if (FileObject->RelatedFileObject)
94 {
95 DPRINT("Converting relative filename to absolute filename\n");
96
97 Status = NtfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
98 FileName,
99 &AbsFileName);
100 FileName = AbsFileName;
101 if (!NT_SUCCESS(Status))
102 {
103 return Status;
104 }
105
106 return STATUS_UNSUCCESSFUL;
107 }
108
109 //FIXME: Get cannonical path name (remove .'s, ..'s and extra separators)
110
111 DPRINT("PathName to open: %S\n", FileName);
112
113 /* try first to find an existing FCB in memory */
114 DPRINT("Checking for existing FCB in memory\n");
115 Fcb = NtfsGrabFCBFromTable(DeviceExt,
116 FileName);
117 if (Fcb == NULL)
118 {
119 DPRINT("No existing FCB found, making a new one if file exists.\n");
120 Status = NtfsGetFCBForFile(DeviceExt,
121 &ParentFcb,
122 &Fcb,
123 FileName);
124 if (ParentFcb != NULL)
125 {
126 NtfsReleaseFCB(DeviceExt,
127 ParentFcb);
128 }
129
130 if (!NT_SUCCESS (Status))
131 {
132 DPRINT("Could not make a new FCB, status: %x\n", Status);
133
134 if (AbsFileName)
135 ExFreePool(AbsFileName);
136
137 return Status;
138 }
139 }
140
141 DPRINT("Attaching FCB to fileObject\n");
142 Status = NtfsAttachFCBToFileObject(DeviceExt,
143 Fcb,
144 FileObject);
145
146 if (AbsFileName)
147 ExFreePool(AbsFileName);
148
149 *FoundFCB = Fcb;
150
151 return Status;
152 }
153
154
155 /*
156 * FUNCTION: Opens a file
157 */
158 static
159 NTSTATUS
160 NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
161 PIRP Irp)
162 {
163 PDEVICE_EXTENSION DeviceExt;
164 PIO_STACK_LOCATION Stack;
165 PFILE_OBJECT FileObject;
166 ULONG RequestedDisposition;
167 ULONG RequestedOptions;
168 PNTFS_FCB Fcb;
169 // PWSTR FileName;
170 NTSTATUS Status;
171
172 DPRINT1("NtfsCreateFile(%p, %p) called\n", DeviceObject, Irp);
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 // PagingFileCreate = (Stack->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE;
182 if (RequestedOptions & FILE_DIRECTORY_FILE &&
183 RequestedDisposition == FILE_SUPERSEDE)
184 {
185 return STATUS_INVALID_PARAMETER;
186 }
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 /* This a open operation for the volume itself */
198 if (FileObject->FileName.Length == 0 &&
199 (FileObject->RelatedFileObject == NULL || FileObject->RelatedFileObject->FsContext2 != NULL))
200 {
201 if (RequestedDisposition != FILE_OPEN &&
202 RequestedDisposition != FILE_OPEN_IF)
203 {
204 return STATUS_ACCESS_DENIED;
205 }
206
207 if (RequestedOptions & FILE_DIRECTORY_FILE)
208 {
209 return STATUS_NOT_A_DIRECTORY;
210 }
211
212 NtfsAttachFCBToFileObject(DeviceExt, DeviceExt->VolumeFcb, FileObject);
213 DeviceExt->VolumeFcb->RefCount++;
214
215 Irp->IoStatus.Information = FILE_OPENED;
216 return STATUS_SUCCESS;
217 }
218
219 Status = NtfsOpenFile(DeviceExt,
220 FileObject,
221 FileObject->FileName.Buffer,
222 &Fcb);
223
224 /*
225 * If the directory containing the file to open doesn't exist then
226 * fail immediately
227 */
228 Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0;
229 Irp->IoStatus.Status = Status;
230
231 return Status;
232 }
233
234
235 NTSTATUS
236 NTAPI
237 NtfsFsdCreate(PDEVICE_OBJECT DeviceObject,
238 PIRP Irp)
239 {
240 PDEVICE_EXTENSION DeviceExt;
241 NTSTATUS Status;
242
243 if (DeviceObject == NtfsGlobalData->DeviceObject)
244 {
245 /* DeviceObject represents FileSystem instead of logical volume */
246 DPRINT("Opening file system\n");
247 Irp->IoStatus.Information = FILE_OPENED;
248 Status = STATUS_SUCCESS;
249 goto ByeBye;
250 }
251
252 DeviceExt = DeviceObject->DeviceExtension;
253
254 FsRtlEnterFileSystem();
255 ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
256 TRUE);
257 Status = NtfsCreateFile(DeviceObject,
258 Irp);
259 ExReleaseResourceLite(&DeviceExt->DirResource);
260 FsRtlExitFileSystem();
261
262 ByeBye:
263 Irp->IoStatus.Status = Status;
264 IoCompleteRequest(Irp,
265 NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT);
266
267 return Status;
268 }
269
270 /* EOF */