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 ]
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)
16 /* INCLUDES *****************************************************************/
21 #include "../include/debug.h"
24 /* FUNCTIONS ****************************************************************/
29 HANDLE STDCALL
CreateFileA (LPCSTR lpFileName
,
30 DWORD dwDesiredAccess
,
32 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
33 DWORD dwCreationDisposition
,
34 DWORD dwFlagsAndAttributes
,
37 UNICODE_STRING FileNameU
;
41 DPRINT("CreateFileA(lpFileName %s)\n",lpFileName
);
43 RtlInitAnsiString (&FileName
,
46 /* convert ansi (or oem) string to unicode */
48 RtlAnsiStringToUnicodeString (&FileNameU
,
52 RtlOemStringToUnicodeString (&FileNameU
,
56 FileHandle
= CreateFileW (FileNameU
.Buffer
,
60 dwCreationDisposition
,
64 RtlFreeHeap (RtlGetProcessHeap (),
75 HANDLE STDCALL
CreateFileW (LPCWSTR lpFileName
,
76 DWORD dwDesiredAccess
,
78 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
79 DWORD dwCreationDisposition
,
80 DWORD dwFlagsAndAttributes
,
83 OBJECT_ATTRIBUTES ObjectAttributes
;
84 IO_STATUS_BLOCK IoStatusBlock
;
85 UNICODE_STRING NtPathU
;
88 ULONG FileAttributes
, Flags
= 0;
89 CSRSS_API_REQUEST Request
;
90 CSRSS_API_REPLY Reply
;
91 PVOID EaBuffer
= NULL
;
94 DPRINT("CreateFileW(lpFileName %S)\n",lpFileName
);
96 /* validate & translate the creation disposition */
97 switch (dwCreationDisposition
)
100 dwCreationDisposition
= FILE_CREATE
;
104 dwCreationDisposition
= FILE_OVERWRITE_IF
;
108 dwCreationDisposition
= FILE_OPEN
;
112 dwCreationDisposition
= FILE_OPEN_IF
;
115 case TRUNCATE_EXISTING
:
116 dwCreationDisposition
= FILE_OVERWRITE
;
120 SetLastError(ERROR_INVALID_PARAMETER
);
121 return (INVALID_HANDLE_VALUE
);
124 /* validate & translate the filename */
125 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpFileName
,
130 DPRINT("Invalid path\n");
131 SetLastError(ERROR_PATH_NOT_FOUND
);
132 return INVALID_HANDLE_VALUE
;
135 DPRINT("NtPathU \'%S\'\n", NtPathU
.Buffer
);
137 /* validate & translate the flags */
139 /* translate the flags that need no validation */
140 if (!(dwFlagsAndAttributes
& FILE_FLAG_OVERLAPPED
))
142 /* yes, nonalert is correct! apc's are not delivered
143 while waiting for file io to complete */
144 Flags
|= FILE_SYNCHRONOUS_IO_NONALERT
;
147 if(dwFlagsAndAttributes
& FILE_FLAG_WRITE_THROUGH
)
148 Flags
|= FILE_WRITE_THROUGH
;
150 if(dwFlagsAndAttributes
& FILE_FLAG_NO_BUFFERING
)
151 Flags
|= FILE_NO_INTERMEDIATE_BUFFERING
;
153 if(dwFlagsAndAttributes
& FILE_FLAG_RANDOM_ACCESS
)
154 Flags
|= FILE_RANDOM_ACCESS
;
156 if(dwFlagsAndAttributes
& FILE_FLAG_SEQUENTIAL_SCAN
)
157 Flags
|= FILE_SEQUENTIAL_ONLY
;
159 if(dwFlagsAndAttributes
& FILE_FLAG_DELETE_ON_CLOSE
)
160 Flags
|= FILE_DELETE_ON_CLOSE
;
162 if(dwFlagsAndAttributes
& FILE_FLAG_BACKUP_SEMANTICS
)
164 if(dwDesiredAccess
& GENERIC_ALL
)
165 Flags
|= FILE_OPEN_FOR_BACKUP_INTENT
| FILE_OPEN_FOR_RECOVERY
;
168 if(dwDesiredAccess
& GENERIC_READ
)
169 Flags
|= FILE_OPEN_FOR_BACKUP_INTENT
;
171 if(dwDesiredAccess
& GENERIC_WRITE
)
172 Flags
|= FILE_OPEN_FOR_RECOVERY
;
176 Flags
|= FILE_NON_DIRECTORY_FILE
;
178 if(dwFlagsAndAttributes
& FILE_FLAG_OPEN_REPARSE_POINT
)
179 Flags
|= FILE_OPEN_REPARSE_POINT
;
181 if(dwFlagsAndAttributes
& FILE_FLAG_OPEN_NO_RECALL
)
182 Flags
|= FILE_OPEN_NO_RECALL
;
184 FileAttributes
= (dwFlagsAndAttributes
& (FILE_ATTRIBUTE_VALID_FLAGS
& ~FILE_ATTRIBUTE_DIRECTORY
));
186 /* handle may allways be waited on and querying attributes are allways allowed */
187 dwDesiredAccess
|= SYNCHRONIZE
| FILE_READ_ATTRIBUTES
;
189 /* FILE_FLAG_POSIX_SEMANTICS is handled later */
191 /* check for console output */
192 if (0 == _wcsicmp(L
"CONOUT$", lpFileName
))
194 /* FIXME: Send required access rights to Csrss */
195 Request
.Type
= CSRSS_GET_OUTPUT_HANDLE
;
196 Status
= CsrClientCallServer(&Request
,
198 sizeof(CSRSS_API_REQUEST
),
199 sizeof(CSRSS_API_REPLY
));
200 if (!NT_SUCCESS(Status
) || !NT_SUCCESS(Status
= Reply
.Status
))
202 SetLastErrorByStatus(Status
);
203 return INVALID_HANDLE_VALUE
;
207 return Reply
.Data
.GetOutputHandleReply
.OutputHandle
;
211 /* check for console input */
212 if (0 == _wcsicmp(L
"CONIN$", lpFileName
))
214 /* FIXME: Send required access rights to Csrss */
215 Request
.Type
= CSRSS_GET_INPUT_HANDLE
;
216 Status
= CsrClientCallServer(&Request
,
218 sizeof(CSRSS_API_REQUEST
),
219 sizeof(CSRSS_API_REPLY
));
220 if (!NT_SUCCESS(Status
) || !NT_SUCCESS(Status
= Reply
.Status
))
222 SetLastErrorByStatus(Status
);
223 return INVALID_HANDLE_VALUE
;
227 return Reply
.Data
.GetInputHandleReply
.InputHandle
;
231 if (hTemplateFile
!= NULL
)
233 FILE_EA_INFORMATION EaInformation
;
237 /* try to get the size of the extended attributes, if we fail just continue
238 creating the file without copying the attributes! */
239 Status
= NtQueryInformationFile(hTemplateFile
,
242 sizeof(FILE_EA_INFORMATION
),
244 if (NT_SUCCESS(Status
) && (EaInformation
.EaSize
!= 0))
246 /* there's extended attributes to read, let's give it a try */
247 EaBuffer
= RtlAllocateHeap(RtlGetProcessHeap(),
249 EaInformation
.EaSize
);
250 if (EaBuffer
== NULL
)
252 /* the template file handle is valid and has extended attributes,
253 however we seem to lack some memory here. We should fail here! */
254 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
255 return INVALID_HANDLE_VALUE
;
258 Status
= NtQueryEaFile(hTemplateFile
,
261 EaInformation
.EaSize
,
268 if (NT_SUCCESS(Status
))
270 /* we successfully read the extended attributes, break the loop
272 EaLength
= EaInformation
.EaSize
;
277 RtlFreeHeap(RtlGetProcessHeap(),
282 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
284 /* unless we just allocated not enough memory, break the loop
285 and just continue without copying extended attributes */
292 /* we either failed to get the size of the extended attributes or
293 they're empty, just continue as there's no need to copy
300 /* build the object attributes */
301 InitializeObjectAttributes(&ObjectAttributes
,
307 if (lpSecurityAttributes
)
309 if(lpSecurityAttributes
->bInheritHandle
)
310 ObjectAttributes
.Attributes
|= OBJ_INHERIT
;
312 ObjectAttributes
.SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
315 if(!(dwFlagsAndAttributes
& FILE_FLAG_POSIX_SEMANTICS
))
316 ObjectAttributes
.Attributes
|= OBJ_CASE_INSENSITIVE
;
318 /* perform the call */
319 Status
= NtCreateFile (&FileHandle
,
326 dwCreationDisposition
,
331 RtlFreeUnicodeString(&NtPathU
);
333 /* free the extended attributes buffer if allocated */
334 if (EaBuffer
!= NULL
)
336 RtlFreeHeap(RtlGetProcessHeap(),
342 if (!NT_SUCCESS(Status
))
344 /* In the case file creation was rejected due to CREATE_NEW flag
345 * was specified and file with that name already exists, correct
346 * last error is ERROR_FILE_EXISTS and not ERROR_ALREADY_EXISTS.
347 * Note: RtlNtStatusToDosError is not the subject to blame here.
349 if (Status
== STATUS_OBJECT_NAME_COLLISION
&&
350 dwCreationDisposition
== FILE_CREATE
)
352 SetLastError( ERROR_FILE_EXISTS
);
356 SetLastErrorByStatus (Status
);
359 return INVALID_HANDLE_VALUE
;
363 create with OPEN_ALWAYS (FILE_OPEN_IF) returns info = FILE_OPENED or FILE_CREATED
364 create with CREATE_ALWAYS (FILE_OVERWRITE_IF) returns info = FILE_OVERWRITTEN or FILE_CREATED
366 if (dwCreationDisposition
== FILE_OPEN_IF
)
368 SetLastError(IoStatusBlock
.Information
== FILE_OPENED
? ERROR_ALREADY_EXISTS
: 0);
370 else if (dwCreationDisposition
== FILE_OVERWRITE_IF
)
372 SetLastError(IoStatusBlock
.Information
== FILE_OVERWRITTEN
? ERROR_ALREADY_EXISTS
: 0);