- Convert the user mode dwDesiredAccess flags in CreateFile to the kernel mode ones...
[reactos.git] / reactos / lib / kernel32 / file / create.c
1 /* $Id: create.c,v 1.37 2004/07/18 17:08:29 navaraf Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/file/create.c
6 * PURPOSE: Directory functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
8 * GetTempFileName is modified from WINE [ Alexandre Juiliard ]
9 * UPDATE HISTORY:
10 * Created 01/11/98
11 * Removed use of SearchPath (not used by Windows)
12 * 18/08/2002: CreateFileW mess cleaned up (KJK::Hyperion)
13 * 24/08/2002: removed superfluous DPRINTs (KJK::Hyperion)
14 */
15
16 /* INCLUDES *****************************************************************/
17
18 #include <k32.h>
19
20 #define NDEBUG
21 #include "../include/debug.h"
22
23
24 /* FUNCTIONS ****************************************************************/
25
26 /*
27 * @implemented
28 */
29 HANDLE STDCALL CreateFileA (LPCSTR lpFileName,
30 DWORD dwDesiredAccess,
31 DWORD dwShareMode,
32 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
33 DWORD dwCreationDisposition,
34 DWORD dwFlagsAndAttributes,
35 HANDLE hTemplateFile)
36 {
37 UNICODE_STRING FileNameU;
38 ANSI_STRING FileName;
39 HANDLE FileHandle;
40
41 DPRINT("CreateFileA(lpFileName %s)\n",lpFileName);
42
43 RtlInitAnsiString (&FileName,
44 (LPSTR)lpFileName);
45
46 /* convert ansi (or oem) string to unicode */
47 if (bIsFileApiAnsi)
48 RtlAnsiStringToUnicodeString (&FileNameU,
49 &FileName,
50 TRUE);
51 else
52 RtlOemStringToUnicodeString (&FileNameU,
53 &FileName,
54 TRUE);
55
56 FileHandle = CreateFileW (FileNameU.Buffer,
57 dwDesiredAccess,
58 dwShareMode,
59 lpSecurityAttributes,
60 dwCreationDisposition,
61 dwFlagsAndAttributes,
62 hTemplateFile);
63
64 RtlFreeHeap (RtlGetProcessHeap (),
65 0,
66 FileNameU.Buffer);
67
68 return FileHandle;
69 }
70
71
72 /*
73 * @implemented
74 */
75 HANDLE STDCALL CreateFileW (LPCWSTR lpFileName,
76 DWORD dwDesiredAccess,
77 DWORD dwShareMode,
78 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
79 DWORD dwCreationDisposition,
80 DWORD dwFlagsAndAttributes,
81 HANDLE hTemplateFile)
82 {
83 OBJECT_ATTRIBUTES ObjectAttributes;
84 IO_STATUS_BLOCK IoStatusBlock;
85 UNICODE_STRING NtPathU;
86 HANDLE FileHandle;
87 NTSTATUS Status;
88 ULONG Flags = 0;
89 ULONG DesiredAccess = 0;
90 CSRSS_API_REQUEST Request;
91 CSRSS_API_REPLY Reply;
92
93 DPRINT("CreateFileW(lpFileName %S)\n",lpFileName);
94
95 if(hTemplateFile != NULL)
96 {
97 /* FIXME */
98 DPRINT("Template file feature not supported yet\n");
99 SetLastError(ERROR_NOT_SUPPORTED);
100 return INVALID_HANDLE_VALUE;
101 }
102
103 /* validate & translate the creation disposition */
104 switch (dwCreationDisposition)
105 {
106 case CREATE_NEW:
107 dwCreationDisposition = FILE_CREATE;
108 break;
109
110 case CREATE_ALWAYS:
111 dwCreationDisposition = FILE_OVERWRITE_IF;
112 break;
113
114 case OPEN_EXISTING:
115 dwCreationDisposition = FILE_OPEN;
116 break;
117
118 case OPEN_ALWAYS:
119 dwCreationDisposition = FILE_OPEN_IF;
120 break;
121
122 case TRUNCATE_EXISTING:
123 dwCreationDisposition = FILE_OVERWRITE;
124 break;
125
126 default:
127 SetLastError(ERROR_INVALID_PARAMETER);
128 return (INVALID_HANDLE_VALUE);
129 }
130
131 /* validate & translate the filename */
132 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFileName,
133 &NtPathU,
134 NULL,
135 NULL))
136 {
137 DPRINT("Invalid path\n");
138 SetLastError(ERROR_BAD_PATHNAME);
139 return INVALID_HANDLE_VALUE;
140 }
141
142 DPRINT("NtPathU \'%S\'\n", NtPathU.Buffer);
143
144 /* validate & translate the flags */
145
146 /* translate the flags that need no validation */
147 if (!(dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)){
148 /* yes, nonalert is correct! apc's are not delivered
149 while waiting for file io to complete */
150 Flags |= FILE_SYNCHRONOUS_IO_NONALERT;
151 }
152
153 if(dwFlagsAndAttributes & FILE_FLAG_WRITE_THROUGH)
154 Flags |= FILE_WRITE_THROUGH;
155
156 if(dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING)
157 Flags |= FILE_NO_INTERMEDIATE_BUFFERING;
158
159 if(dwFlagsAndAttributes & FILE_FLAG_RANDOM_ACCESS)
160 Flags |= FILE_RANDOM_ACCESS;
161
162 if(dwFlagsAndAttributes & FILE_FLAG_SEQUENTIAL_SCAN)
163 Flags |= FILE_SEQUENTIAL_ONLY;
164
165 if(dwFlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE)
166 Flags |= FILE_DELETE_ON_CLOSE;
167
168 if(dwFlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS)
169 {
170 if(dwDesiredAccess & GENERIC_ALL)
171 Flags |= FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_FOR_RECOVERY;
172 else
173 {
174 if(dwDesiredAccess & GENERIC_READ)
175 Flags |= FILE_OPEN_FOR_BACKUP_INTENT;
176
177 if(dwDesiredAccess & GENERIC_WRITE)
178 Flags |= FILE_OPEN_FOR_RECOVERY;
179 }
180 }
181 else
182 {
183 Flags |= FILE_NON_DIRECTORY_FILE;
184 }
185
186 if(dwDesiredAccess & GENERIC_ALL)
187 DesiredAccess |= FILE_READ_DATA | FILE_WRITE_DATA;
188 else
189 {
190 if(dwDesiredAccess & GENERIC_READ)
191 DesiredAccess |= FILE_READ_DATA;
192
193 if(dwDesiredAccess & GENERIC_WRITE)
194 DesiredAccess |= FILE_WRITE_DATA;
195 }
196
197 /* handle may allways be waited on and querying attributes are allways allowed */
198 DesiredAccess |= SYNCHRONIZE|FILE_READ_ATTRIBUTES;
199
200 /* FILE_FLAG_POSIX_SEMANTICS is handled later */
201
202 #if 0
203 /* FIXME: Win32 constants to be defined */
204 if(dwFlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT)
205 Flags |= FILE_OPEN_REPARSE_POINT;
206
207 if(dwFlagsAndAttributes & FILE_FLAG_OPEN_NO_RECALL)
208 Flags |= FILE_OPEN_NO_RECALL;
209 #endif
210
211 /* check for console output */
212 if (0 == _wcsicmp(L"CONOUT$", lpFileName))
213 {
214 /* FIXME: Send required access rights to Csrss */
215 Request.Type = CSRSS_GET_OUTPUT_HANDLE;
216 Status = CsrClientCallServer(&Request,
217 &Reply,
218 sizeof(CSRSS_API_REQUEST),
219 sizeof(CSRSS_API_REPLY));
220 if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
221 {
222 SetLastErrorByStatus(Status);
223 return INVALID_HANDLE_VALUE;
224 }
225 else
226 {
227 return Reply.Data.GetOutputHandleReply.OutputHandle;
228 }
229 }
230
231 /* check for console input */
232 if (0 == _wcsicmp(L"CONIN$", lpFileName))
233 {
234 /* FIXME: Send required access rights to Csrss */
235 Request.Type = CSRSS_GET_INPUT_HANDLE;
236 Status = CsrClientCallServer(&Request,
237 &Reply,
238 sizeof(CSRSS_API_REQUEST),
239 sizeof(CSRSS_API_REPLY));
240 if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
241 {
242 SetLastErrorByStatus(Status);
243 return INVALID_HANDLE_VALUE;
244 }
245 else
246 {
247 return Reply.Data.GetInputHandleReply.InputHandle;
248 }
249 }
250
251 /* build the object attributes */
252 InitializeObjectAttributes(
253 &ObjectAttributes,
254 &NtPathU,
255 0,
256 NULL,
257 NULL
258 );
259
260 if (lpSecurityAttributes)
261 {
262 if(lpSecurityAttributes->bInheritHandle)
263 ObjectAttributes.Attributes |= OBJ_INHERIT;
264
265 ObjectAttributes.SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
266 }
267
268 if(!(dwFlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS))
269 ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
270
271 /* perform the call */
272 Status = NtCreateFile (&FileHandle,
273 DesiredAccess,
274 &ObjectAttributes,
275 &IoStatusBlock,
276 NULL,
277 dwFlagsAndAttributes,
278 dwShareMode,
279 dwCreationDisposition,
280 Flags,
281 NULL,
282 0);
283
284 RtlFreeUnicodeString(&NtPathU);
285
286 /* error */
287 if (!NT_SUCCESS(Status))
288 {
289 SetLastErrorByStatus (Status);
290 return INVALID_HANDLE_VALUE;
291 }
292
293 /*
294 create with OPEN_ALWAYS (FILE_OPEN_IF) returns info = FILE_OPENED or FILE_CREATED
295 create with CREATE_ALWAYS (FILE_OVERWRITE_IF) returns info = FILE_OVERWRITTEN or FILE_CREATED
296 */
297 if ((dwCreationDisposition == FILE_OPEN_IF && IoStatusBlock.Information == FILE_OPENED) ||
298 (dwCreationDisposition == FILE_OVERWRITE_IF && IoStatusBlock.Information == FILE_OVERWRITTEN))
299 {
300 SetLastError(ERROR_ALREADY_EXISTS);
301 }
302
303 return FileHandle;
304 }
305
306 /* EOF */