2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/kernel32/client/file/create.c
5 * PURPOSE: Directory functions
6 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
9 * Removed use of SearchPath (not used by Windows)
10 * 18/08/2002: CreateFileW mess cleaned up (KJK::Hyperion)
11 * 24/08/2002: removed superfluous DPRINTs (KJK::Hyperion)
14 /* INCLUDES *****************************************************************/
21 DEBUG_CHANNEL(kernel32file
);
24 /* FUNCTIONS ****************************************************************/
29 HANDLE WINAPI
CreateFileA (LPCSTR lpFileName
,
30 DWORD dwDesiredAccess
,
32 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
33 DWORD dwCreationDisposition
,
34 DWORD dwFlagsAndAttributes
,
40 TRACE("CreateFileA(lpFileName %s)\n",lpFileName
);
42 if (!(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
43 return INVALID_HANDLE_VALUE
;
45 FileHandle
= CreateFileW (FileNameW
,
49 dwCreationDisposition
,
60 HANDLE WINAPI
CreateFileW (LPCWSTR lpFileName
,
61 DWORD dwDesiredAccess
,
63 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
64 DWORD dwCreationDisposition
,
65 DWORD dwFlagsAndAttributes
,
68 OBJECT_ATTRIBUTES ObjectAttributes
;
69 IO_STATUS_BLOCK IoStatusBlock
;
70 UNICODE_STRING NtPathU
;
71 LPCWSTR pszConsoleFileName
;
74 ULONG FileAttributes
, Flags
= 0;
75 PVOID EaBuffer
= NULL
;
77 BOOLEAN TrailingBackslash
;
79 if (!lpFileName
|| !lpFileName
[0])
81 SetLastError( ERROR_PATH_NOT_FOUND
);
82 return INVALID_HANDLE_VALUE
;
85 TRACE("CreateFileW(lpFileName %S)\n",lpFileName
);
87 /* validate & translate the creation disposition */
88 switch (dwCreationDisposition
)
91 dwCreationDisposition
= FILE_CREATE
;
95 dwCreationDisposition
= FILE_OVERWRITE_IF
;
99 dwCreationDisposition
= FILE_OPEN
;
103 dwCreationDisposition
= FILE_OPEN_IF
;
106 case TRUNCATE_EXISTING
:
107 dwCreationDisposition
= FILE_OVERWRITE
;
111 SetLastError(ERROR_INVALID_PARAMETER
);
112 return (INVALID_HANDLE_VALUE
);
115 /* check for console input/output */
116 pszConsoleFileName
= IntCheckForConsoleFileName(lpFileName
, dwDesiredAccess
);
117 if (pszConsoleFileName
)
119 return OpenConsoleW(pszConsoleFileName
,
121 lpSecurityAttributes
? lpSecurityAttributes
->bInheritHandle
: FALSE
,
122 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
125 /* validate & translate the flags */
127 /* translate the flags that need no validation */
128 if (!(dwFlagsAndAttributes
& FILE_FLAG_OVERLAPPED
))
130 /* yes, nonalert is correct! apc's are not delivered
131 while waiting for file io to complete */
132 Flags
|= FILE_SYNCHRONOUS_IO_NONALERT
;
135 if(dwFlagsAndAttributes
& FILE_FLAG_WRITE_THROUGH
)
136 Flags
|= FILE_WRITE_THROUGH
;
138 if(dwFlagsAndAttributes
& FILE_FLAG_NO_BUFFERING
)
139 Flags
|= FILE_NO_INTERMEDIATE_BUFFERING
;
141 if(dwFlagsAndAttributes
& FILE_FLAG_RANDOM_ACCESS
)
142 Flags
|= FILE_RANDOM_ACCESS
;
144 if(dwFlagsAndAttributes
& FILE_FLAG_SEQUENTIAL_SCAN
)
145 Flags
|= FILE_SEQUENTIAL_ONLY
;
147 if(dwFlagsAndAttributes
& FILE_FLAG_DELETE_ON_CLOSE
)
149 Flags
|= FILE_DELETE_ON_CLOSE
;
150 dwDesiredAccess
|= DELETE
;
153 if(dwFlagsAndAttributes
& FILE_FLAG_BACKUP_SEMANTICS
)
155 if(dwDesiredAccess
& GENERIC_ALL
)
156 Flags
|= FILE_OPEN_FOR_BACKUP_INTENT
| FILE_OPEN_REMOTE_INSTANCE
;
159 if(dwDesiredAccess
& GENERIC_READ
)
160 Flags
|= FILE_OPEN_FOR_BACKUP_INTENT
;
162 if(dwDesiredAccess
& GENERIC_WRITE
)
163 Flags
|= FILE_OPEN_REMOTE_INSTANCE
;
167 Flags
|= FILE_NON_DIRECTORY_FILE
;
169 if(dwFlagsAndAttributes
& FILE_FLAG_OPEN_REPARSE_POINT
)
170 Flags
|= FILE_OPEN_REPARSE_POINT
;
172 if(dwFlagsAndAttributes
& FILE_FLAG_OPEN_NO_RECALL
)
173 Flags
|= FILE_OPEN_NO_RECALL
;
175 FileAttributes
= (dwFlagsAndAttributes
& (FILE_ATTRIBUTE_VALID_FLAGS
& ~FILE_ATTRIBUTE_DIRECTORY
));
177 /* handle may always be waited on and querying attributes are always allowed */
178 dwDesiredAccess
|= SYNCHRONIZE
| FILE_READ_ATTRIBUTES
;
180 /* FILE_FLAG_POSIX_SEMANTICS is handled later */
182 /* validate & translate the filename */
183 if (!RtlDosPathNameToNtPathName_U (lpFileName
,
188 WARN("Invalid path\n");
189 SetLastError(ERROR_FILE_NOT_FOUND
);
190 return INVALID_HANDLE_VALUE
;
193 TRACE("NtPathU \'%wZ\'\n", &NtPathU
);
195 TrailingBackslash
= FALSE
;
196 if (NtPathU
.Length
>= sizeof(WCHAR
) &&
197 NtPathU
.Buffer
[NtPathU
.Length
/ sizeof(WCHAR
) - 1])
199 TrailingBackslash
= TRUE
;
202 if (hTemplateFile
!= NULL
)
204 FILE_EA_INFORMATION EaInformation
;
208 /* try to get the size of the extended attributes, if we fail just continue
209 creating the file without copying the attributes! */
210 Status
= NtQueryInformationFile(hTemplateFile
,
213 sizeof(FILE_EA_INFORMATION
),
215 if (NT_SUCCESS(Status
) && (EaInformation
.EaSize
!= 0))
217 /* there's extended attributes to read, let's give it a try */
218 EaBuffer
= RtlAllocateHeap(RtlGetProcessHeap(),
220 EaInformation
.EaSize
);
221 if (EaBuffer
== NULL
)
223 RtlFreeHeap(RtlGetProcessHeap(),
227 /* the template file handle is valid and has extended attributes,
228 however we seem to lack some memory here. We should fail here! */
229 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
230 return INVALID_HANDLE_VALUE
;
233 Status
= NtQueryEaFile(hTemplateFile
,
236 EaInformation
.EaSize
,
243 if (NT_SUCCESS(Status
))
245 /* we successfully read the extended attributes, break the loop
247 EaLength
= EaInformation
.EaSize
;
252 RtlFreeHeap(RtlGetProcessHeap(),
257 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
259 /* unless we just allocated not enough memory, break the loop
260 and just continue without copying extended attributes */
267 /* we either failed to get the size of the extended attributes or
268 they're empty, just continue as there's no need to copy
275 /* build the object attributes */
276 InitializeObjectAttributes(&ObjectAttributes
,
282 if (lpSecurityAttributes
)
284 if(lpSecurityAttributes
->bInheritHandle
)
285 ObjectAttributes
.Attributes
|= OBJ_INHERIT
;
287 ObjectAttributes
.SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
290 if(!(dwFlagsAndAttributes
& FILE_FLAG_POSIX_SEMANTICS
))
291 ObjectAttributes
.Attributes
|= OBJ_CASE_INSENSITIVE
;
293 /* perform the call */
294 Status
= NtCreateFile (&FileHandle
,
301 dwCreationDisposition
,
306 RtlFreeHeap(RtlGetProcessHeap(),
310 /* free the extended attributes buffer if allocated */
311 if (EaBuffer
!= NULL
)
313 RtlFreeHeap(RtlGetProcessHeap(),
319 if (!NT_SUCCESS(Status
))
321 /* In the case file creation was rejected due to CREATE_NEW flag
322 * was specified and file with that name already exists, correct
323 * last error is ERROR_FILE_EXISTS and not ERROR_ALREADY_EXISTS.
324 * Note: RtlNtStatusToDosError is not the subject to blame here.
326 if (Status
== STATUS_OBJECT_NAME_COLLISION
&&
327 dwCreationDisposition
== FILE_CREATE
)
329 SetLastError( ERROR_FILE_EXISTS
);
331 else if (Status
== STATUS_FILE_IS_A_DIRECTORY
&&
334 SetLastError(ERROR_PATH_NOT_FOUND
);
338 BaseSetLastNTError (Status
);
341 return INVALID_HANDLE_VALUE
;
345 create with OPEN_ALWAYS (FILE_OPEN_IF) returns info = FILE_OPENED or FILE_CREATED
346 create with CREATE_ALWAYS (FILE_OVERWRITE_IF) returns info = FILE_OVERWRITTEN or FILE_CREATED
348 if (dwCreationDisposition
== FILE_OPEN_IF
)
350 SetLastError(IoStatusBlock
.Information
== FILE_OPENED
? ERROR_ALREADY_EXISTS
: ERROR_SUCCESS
);
352 else if (dwCreationDisposition
== FILE_OVERWRITE_IF
)
354 SetLastError(IoStatusBlock
.Information
== FILE_OVERWRITTEN
? ERROR_ALREADY_EXISTS
: ERROR_SUCCESS
);
358 SetLastError(ERROR_SUCCESS
);
368 OpenFile(LPCSTR lpFileName
,
369 LPOFSTRUCT lpReOpenBuff
,
372 OBJECT_ATTRIBUTES ObjectAttributes
;
373 IO_STATUS_BLOCK IoStatusBlock
;
374 UNICODE_STRING FileNameString
;
375 UNICODE_STRING FileNameU
;
376 ANSI_STRING FileName
;
377 WCHAR PathNameW
[MAX_PATH
];
378 HANDLE FileHandle
= NULL
;
383 TRACE("OpenFile('%s', lpReOpenBuff %p, uStyle %x)\n", lpFileName
, lpReOpenBuff
, uStyle
);
385 if (lpReOpenBuff
== NULL
)
390 lpReOpenBuff
->nErrCode
= 0;
392 if (uStyle
& OF_REOPEN
) lpFileName
= lpReOpenBuff
->szPathName
;
399 if (!GetFullPathNameA(lpFileName
,
400 sizeof(lpReOpenBuff
->szPathName
),
401 lpReOpenBuff
->szPathName
,
404 lpReOpenBuff
->nErrCode
= (WORD
)GetLastError();
408 if (uStyle
& OF_PARSE
)
410 lpReOpenBuff
->fFixedDisk
= (GetDriveTypeA(lpReOpenBuff
->szPathName
) != DRIVE_REMOVABLE
);
411 TRACE("(%s): OF_PARSE, res = '%s'\n", lpFileName
, lpReOpenBuff
->szPathName
);
415 if ((uStyle
& OF_EXIST
) && !(uStyle
& OF_CREATE
))
417 DWORD dwAttributes
= GetFileAttributesA(lpReOpenBuff
->szPathName
);
419 switch (dwAttributes
)
421 case INVALID_FILE_ATTRIBUTES
: /* File does not exist */
422 SetLastError(ERROR_FILE_NOT_FOUND
);
423 lpReOpenBuff
->nErrCode
= (WORD
) ERROR_FILE_NOT_FOUND
;
426 case FILE_ATTRIBUTE_DIRECTORY
:
427 SetLastError(ERROR_ACCESS_DENIED
);
428 lpReOpenBuff
->nErrCode
= (WORD
) ERROR_ACCESS_DENIED
;
432 lpReOpenBuff
->cBytes
= sizeof(OFSTRUCT
);
436 lpReOpenBuff
->cBytes
= sizeof(OFSTRUCT
);
437 if ((uStyle
& OF_CREATE
) == OF_CREATE
)
440 switch (uStyle
& 0x70)
442 case OF_SHARE_EXCLUSIVE
: Sharing
= 0; break;
443 case OF_SHARE_DENY_WRITE
: Sharing
= FILE_SHARE_READ
; break;
444 case OF_SHARE_DENY_READ
: Sharing
= FILE_SHARE_WRITE
; break;
445 case OF_SHARE_DENY_NONE
:
446 case OF_SHARE_COMPAT
:
448 Sharing
= FILE_SHARE_READ
| FILE_SHARE_WRITE
;
450 return (HFILE
)(ULONG_PTR
) CreateFileA (lpFileName
,
451 GENERIC_READ
| GENERIC_WRITE
,
455 FILE_ATTRIBUTE_NORMAL
,
459 RtlInitAnsiString (&FileName
, (LPSTR
)lpFileName
);
461 /* convert ansi (or oem) string to unicode */
463 RtlAnsiStringToUnicodeString (&FileNameU
, &FileName
, TRUE
);
465 RtlOemStringToUnicodeString (&FileNameU
, &FileName
, TRUE
);
467 Len
= SearchPathW (NULL
,
474 RtlFreeUnicodeString(&FileNameU
);
476 if (Len
== 0 || Len
> OFS_MAXPATHNAME
)
478 lpReOpenBuff
->nErrCode
= (WORD
)GetLastError();
482 if (uStyle
& OF_DELETE
)
484 if (!DeleteFileW(PathNameW
))
486 lpReOpenBuff
->nErrCode
= (WORD
)GetLastError();
489 TRACE("(%s): OF_DELETE return = OK\n", lpFileName
);
493 FileName
.Buffer
= lpReOpenBuff
->szPathName
;
495 FileName
.MaximumLength
= OFS_MAXPATHNAME
;
497 RtlInitUnicodeString(&FileNameU
, PathNameW
);
499 /* convert unicode string to ansi (or oem) */
501 RtlUnicodeStringToAnsiString (&FileName
, &FileNameU
, FALSE
);
503 RtlUnicodeStringToOemString (&FileName
, &FileNameU
, FALSE
);
505 if (!RtlDosPathNameToNtPathName_U (PathNameW
,
514 // FILE_NO_INTERMEDIATE_BUFFERING
516 ObjectAttributes
.Length
= sizeof(OBJECT_ATTRIBUTES
);
517 ObjectAttributes
.RootDirectory
= NULL
;
518 ObjectAttributes
.ObjectName
= &FileNameString
;
519 ObjectAttributes
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_INHERIT
;
520 ObjectAttributes
.SecurityDescriptor
= NULL
;
521 ObjectAttributes
.SecurityQualityOfService
= NULL
;
523 errCode
= NtOpenFile (&FileHandle
,
524 GENERIC_READ
| SYNCHRONIZE
,
528 FILE_NON_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
530 RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameString
.Buffer
);
532 lpReOpenBuff
->nErrCode
= (WORD
)RtlNtStatusToDosError(errCode
);
534 if (!NT_SUCCESS(errCode
))
536 BaseSetLastNTError (errCode
);
540 if (uStyle
& OF_EXIST
)
546 return (HFILE
)(ULONG_PTR
)FileHandle
;
554 OpenDataFile(HANDLE hFile
, DWORD dwUnused
)
565 ReOpenFile(IN HANDLE hOriginalFile
,
566 IN DWORD dwDesiredAccess
,
567 IN DWORD dwShareMode
,
571 return INVALID_HANDLE_VALUE
;