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