misc
[reactos.git] / reactos / lib / kernel32 / file / create.c
1 /* $Id: create.c,v 1.34 2003/11/27 20:57:58 gdalsnes 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 <kernel32/kernel32.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 CSRSS_API_REQUEST Request;
90 CSRSS_API_REPLY Reply;
91
92 DPRINT("CreateFileW(lpFileName %S)\n",lpFileName);
93
94 if(hTemplateFile != NULL)
95 {
96 /* FIXME */
97 DPRINT("Template file feature not supported yet\n");
98 SetLastError(ERROR_NOT_SUPPORTED);
99 return INVALID_HANDLE_VALUE;
100 }
101
102 /* validate & translate the creation disposition */
103 switch (dwCreationDisposition)
104 {
105 case CREATE_NEW:
106 dwCreationDisposition = FILE_CREATE;
107 break;
108
109 case CREATE_ALWAYS:
110 dwCreationDisposition = FILE_OVERWRITE_IF;
111 break;
112
113 case OPEN_EXISTING:
114 dwCreationDisposition = FILE_OPEN;
115 break;
116
117 case OPEN_ALWAYS:
118 dwCreationDisposition = FILE_OPEN_IF;
119 break;
120
121 case TRUNCATE_EXISTING:
122 dwCreationDisposition = FILE_OVERWRITE;
123 break;
124
125 default:
126 SetLastError(ERROR_INVALID_PARAMETER);
127 return (INVALID_HANDLE_VALUE);
128 }
129
130 /* validate & translate the filename */
131 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFileName,
132 &NtPathU,
133 NULL,
134 NULL))
135 {
136 DPRINT("Invalid path\n");
137 SetLastError(ERROR_BAD_PATHNAME);
138 return INVALID_HANDLE_VALUE;
139 }
140
141 DPRINT("NtPathU \'%S\'\n", NtPathU.Buffer);
142
143 /* validate & translate the flags */
144
145 /* translate the flags that need no validation */
146 if (!(dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)){
147 /* yes, nonalert is correct! apc's are not delivered
148 while waiting for file io to complete */
149 Flags |= FILE_SYNCHRONOUS_IO_NONALERT;
150 }
151
152 if(dwFlagsAndAttributes & FILE_FLAG_WRITE_THROUGH)
153 Flags |= FILE_WRITE_THROUGH;
154
155 if(dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING)
156 Flags |= FILE_NO_INTERMEDIATE_BUFFERING;
157
158 if(dwFlagsAndAttributes & FILE_FLAG_RANDOM_ACCESS)
159 Flags |= FILE_RANDOM_ACCESS;
160
161 if(dwFlagsAndAttributes & FILE_FLAG_SEQUENTIAL_SCAN)
162 Flags |= FILE_SEQUENTIAL_ONLY;
163
164 if(dwFlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE)
165 Flags |= FILE_DELETE_ON_CLOSE;
166
167 if(dwFlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS)
168 {
169 if(dwDesiredAccess & GENERIC_ALL)
170 Flags |= FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_FOR_RECOVERY;
171 else
172 {
173 if(dwDesiredAccess & GENERIC_READ)
174 Flags |= FILE_OPEN_FOR_BACKUP_INTENT;
175
176 if(dwDesiredAccess & GENERIC_WRITE)
177 Flags |= FILE_OPEN_FOR_RECOVERY;
178 }
179 }
180 else
181 Flags |= FILE_NON_DIRECTORY_FILE;
182
183
184 /* handle may allways be waited on and querying attributes are allways allowed */
185 dwDesiredAccess |= SYNCHRONIZE|FILE_READ_ATTRIBUTES;
186
187 /* FILE_FLAG_POSIX_SEMANTICS is handled later */
188
189 #if 0
190 /* FIXME: Win32 constants to be defined */
191 if(dwFlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT)
192 Flags |= FILE_OPEN_REPARSE_POINT;
193
194 if(dwFlagsAndAttributes & FILE_FLAG_OPEN_NO_RECALL)
195 Flags |= FILE_OPEN_NO_RECALL;
196 #endif
197
198 /* check for console output */
199 if (0 == _wcsicmp(L"CONOUT$", lpFileName))
200 {
201 /* FIXME: Send required access rights to Csrss */
202 Request.Type = CSRSS_GET_OUTPUT_HANDLE;
203 Status = CsrClientCallServer(&Request,
204 &Reply,
205 sizeof(CSRSS_API_REQUEST),
206 sizeof(CSRSS_API_REPLY));
207 if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
208 {
209 SetLastErrorByStatus(Status);
210 return INVALID_HANDLE_VALUE;
211 }
212 else
213 {
214 return Reply.Data.GetOutputHandleReply.OutputHandle;
215 }
216 }
217
218 /* check for console input */
219 if (0 == _wcsicmp(L"CONIN$", lpFileName))
220 {
221 /* FIXME: Send required access rights to Csrss */
222 Request.Type = CSRSS_GET_INPUT_HANDLE;
223 Status = CsrClientCallServer(&Request,
224 &Reply,
225 sizeof(CSRSS_API_REQUEST),
226 sizeof(CSRSS_API_REPLY));
227 if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
228 {
229 SetLastErrorByStatus(Status);
230 return INVALID_HANDLE_VALUE;
231 }
232 else
233 {
234 return Reply.Data.GetInputHandleReply.InputHandle;
235 }
236 }
237
238 /* build the object attributes */
239 InitializeObjectAttributes(
240 &ObjectAttributes,
241 &NtPathU,
242 0,
243 NULL,
244 NULL
245 );
246
247 if (lpSecurityAttributes)
248 {
249 if(lpSecurityAttributes->bInheritHandle)
250 ObjectAttributes.Attributes |= OBJ_INHERIT;
251
252 ObjectAttributes.SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
253 }
254
255 if(!(dwFlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS))
256 ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
257
258 /* perform the call */
259 Status = NtCreateFile (&FileHandle,
260 dwDesiredAccess,
261 &ObjectAttributes,
262 &IoStatusBlock,
263 NULL,
264 dwFlagsAndAttributes,
265 dwShareMode,
266 dwCreationDisposition,
267 Flags,
268 NULL,
269 0);
270
271 RtlFreeUnicodeString(&NtPathU);
272
273 /* error */
274 if (!NT_SUCCESS(Status))
275 {
276 SetLastErrorByStatus (Status);
277 return INVALID_HANDLE_VALUE;
278 }
279
280 /*
281 create with OPEN_ALWAYS (FILE_OPEN_IF) returns info = FILE_OPENED or FILE_CREATED
282 create with CREATE_ALWAYS (FILE_OVERWRITE_IF) returns info = FILE_OVERWRITTEN or FILE_CREATED
283 */
284 if ((dwCreationDisposition == FILE_OPEN_IF && IoStatusBlock.Information == FILE_OPENED) ||
285 (dwCreationDisposition == FILE_OVERWRITE_IF && IoStatusBlock.Information == FILE_OVERWRITTEN))
286 {
287 SetLastError(ERROR_ALREADY_EXISTS);
288 }
289 else
290 {
291 SetLastError(0);
292 }
293
294 return FileHandle;
295 }
296
297 /* EOF */