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 #define SYMLINK_FLAG_RELATIVE 1
26 typedef struct _REPARSE_DATA_BUFFER
{
28 USHORT ReparseDataLength
;
32 USHORT SubstituteNameOffset
;
33 USHORT SubstituteNameLength
;
34 USHORT PrintNameOffset
;
35 USHORT PrintNameLength
;
38 } SymbolicLinkReparseBuffer
;
40 USHORT SubstituteNameOffset
;
41 USHORT SubstituteNameLength
;
42 USHORT PrintNameOffset
;
43 USHORT PrintNameLength
;
45 } MountPointReparseBuffer
;
48 } GenericReparseBuffer
;
50 } REPARSE_DATA_BUFFER
, *PREPARSE_DATA_BUFFER
;
52 #define REPARSE_DATA_BUFFER_HEADER_SIZE FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer)
54 /* FUNCTIONS ****************************************************************/
59 HANDLE WINAPI
CreateFileA (LPCSTR lpFileName
,
60 DWORD dwDesiredAccess
,
62 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
63 DWORD dwCreationDisposition
,
64 DWORD dwFlagsAndAttributes
,
70 TRACE("CreateFileA(lpFileName %s)\n",lpFileName
);
72 if (!(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
73 return INVALID_HANDLE_VALUE
;
75 FileHandle
= CreateFileW (FileNameW
,
79 dwCreationDisposition
,
90 HANDLE WINAPI
CreateFileW (LPCWSTR lpFileName
,
91 DWORD dwDesiredAccess
,
93 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
94 DWORD dwCreationDisposition
,
95 DWORD dwFlagsAndAttributes
,
98 OBJECT_ATTRIBUTES ObjectAttributes
;
99 IO_STATUS_BLOCK IoStatusBlock
;
100 UNICODE_STRING NtPathU
;
101 LPCWSTR pszConsoleFileName
;
104 ULONG FileAttributes
, Flags
= 0;
105 PVOID EaBuffer
= NULL
;
107 BOOLEAN TrailingBackslash
;
109 if (!lpFileName
|| !lpFileName
[0])
111 SetLastError( ERROR_PATH_NOT_FOUND
);
112 return INVALID_HANDLE_VALUE
;
115 TRACE("CreateFileW(lpFileName %S)\n",lpFileName
);
117 /* validate & translate the creation disposition */
118 switch (dwCreationDisposition
)
121 dwCreationDisposition
= FILE_CREATE
;
125 dwCreationDisposition
= FILE_OVERWRITE_IF
;
129 dwCreationDisposition
= FILE_OPEN
;
133 dwCreationDisposition
= FILE_OPEN_IF
;
136 case TRUNCATE_EXISTING
:
137 dwCreationDisposition
= FILE_OVERWRITE
;
141 SetLastError(ERROR_INVALID_PARAMETER
);
142 return (INVALID_HANDLE_VALUE
);
145 /* check for console input/output */
146 pszConsoleFileName
= IntCheckForConsoleFileName(lpFileName
, dwDesiredAccess
);
147 if (pszConsoleFileName
)
149 return OpenConsoleW(pszConsoleFileName
,
151 lpSecurityAttributes
? lpSecurityAttributes
->bInheritHandle
: FALSE
,
152 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
155 /* validate & translate the flags */
157 /* translate the flags that need no validation */
158 if (!(dwFlagsAndAttributes
& FILE_FLAG_OVERLAPPED
))
160 /* yes, nonalert is correct! apc's are not delivered
161 while waiting for file io to complete */
162 Flags
|= FILE_SYNCHRONOUS_IO_NONALERT
;
165 if(dwFlagsAndAttributes
& FILE_FLAG_WRITE_THROUGH
)
166 Flags
|= FILE_WRITE_THROUGH
;
168 if(dwFlagsAndAttributes
& FILE_FLAG_NO_BUFFERING
)
169 Flags
|= FILE_NO_INTERMEDIATE_BUFFERING
;
171 if(dwFlagsAndAttributes
& FILE_FLAG_RANDOM_ACCESS
)
172 Flags
|= FILE_RANDOM_ACCESS
;
174 if(dwFlagsAndAttributes
& FILE_FLAG_SEQUENTIAL_SCAN
)
175 Flags
|= FILE_SEQUENTIAL_ONLY
;
177 if(dwFlagsAndAttributes
& FILE_FLAG_DELETE_ON_CLOSE
)
179 Flags
|= FILE_DELETE_ON_CLOSE
;
180 dwDesiredAccess
|= DELETE
;
183 if(dwFlagsAndAttributes
& FILE_FLAG_BACKUP_SEMANTICS
)
185 if(dwDesiredAccess
& GENERIC_ALL
)
186 Flags
|= FILE_OPEN_FOR_BACKUP_INTENT
| FILE_OPEN_REMOTE_INSTANCE
;
189 if(dwDesiredAccess
& GENERIC_READ
)
190 Flags
|= FILE_OPEN_FOR_BACKUP_INTENT
;
192 if(dwDesiredAccess
& GENERIC_WRITE
)
193 Flags
|= FILE_OPEN_REMOTE_INSTANCE
;
197 Flags
|= FILE_NON_DIRECTORY_FILE
;
199 if(dwFlagsAndAttributes
& FILE_FLAG_OPEN_REPARSE_POINT
)
200 Flags
|= FILE_OPEN_REPARSE_POINT
;
202 if(dwFlagsAndAttributes
& FILE_FLAG_OPEN_NO_RECALL
)
203 Flags
|= FILE_OPEN_NO_RECALL
;
205 FileAttributes
= (dwFlagsAndAttributes
& (FILE_ATTRIBUTE_VALID_FLAGS
& ~FILE_ATTRIBUTE_DIRECTORY
));
207 /* handle may always be waited on and querying attributes are always allowed */
208 dwDesiredAccess
|= SYNCHRONIZE
| FILE_READ_ATTRIBUTES
;
210 /* FILE_FLAG_POSIX_SEMANTICS is handled later */
212 /* validate & translate the filename */
213 if (!RtlDosPathNameToNtPathName_U (lpFileName
,
218 WARN("Invalid path\n");
219 SetLastError(ERROR_FILE_NOT_FOUND
);
220 return INVALID_HANDLE_VALUE
;
223 TRACE("NtPathU \'%wZ\'\n", &NtPathU
);
225 TrailingBackslash
= FALSE
;
226 if (NtPathU
.Length
>= sizeof(WCHAR
) &&
227 NtPathU
.Buffer
[NtPathU
.Length
/ sizeof(WCHAR
) - 1])
229 TrailingBackslash
= TRUE
;
232 if (hTemplateFile
!= NULL
)
234 FILE_EA_INFORMATION EaInformation
;
238 /* try to get the size of the extended attributes, if we fail just continue
239 creating the file without copying the attributes! */
240 Status
= NtQueryInformationFile(hTemplateFile
,
243 sizeof(FILE_EA_INFORMATION
),
245 if (NT_SUCCESS(Status
) && (EaInformation
.EaSize
!= 0))
247 /* there's extended attributes to read, let's give it a try */
248 EaBuffer
= RtlAllocateHeap(RtlGetProcessHeap(),
250 EaInformation
.EaSize
);
251 if (EaBuffer
== NULL
)
253 RtlFreeHeap(RtlGetProcessHeap(),
257 /* the template file handle is valid and has extended attributes,
258 however we seem to lack some memory here. We should fail here! */
259 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
260 return INVALID_HANDLE_VALUE
;
263 Status
= NtQueryEaFile(hTemplateFile
,
266 EaInformation
.EaSize
,
273 if (NT_SUCCESS(Status
))
275 /* we successfully read the extended attributes, break the loop
277 EaLength
= EaInformation
.EaSize
;
282 RtlFreeHeap(RtlGetProcessHeap(),
287 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
289 /* unless we just allocated not enough memory, break the loop
290 and just continue without copying extended attributes */
297 /* we either failed to get the size of the extended attributes or
298 they're empty, just continue as there's no need to copy
305 /* build the object attributes */
306 InitializeObjectAttributes(&ObjectAttributes
,
312 if (lpSecurityAttributes
)
314 if(lpSecurityAttributes
->bInheritHandle
)
315 ObjectAttributes
.Attributes
|= OBJ_INHERIT
;
317 ObjectAttributes
.SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
320 if(!(dwFlagsAndAttributes
& FILE_FLAG_POSIX_SEMANTICS
))
321 ObjectAttributes
.Attributes
|= OBJ_CASE_INSENSITIVE
;
323 /* perform the call */
324 Status
= NtCreateFile (&FileHandle
,
331 dwCreationDisposition
,
336 RtlFreeHeap(RtlGetProcessHeap(),
340 /* free the extended attributes buffer if allocated */
341 if (EaBuffer
!= NULL
)
343 RtlFreeHeap(RtlGetProcessHeap(),
349 if (!NT_SUCCESS(Status
))
351 /* In the case file creation was rejected due to CREATE_NEW flag
352 * was specified and file with that name already exists, correct
353 * last error is ERROR_FILE_EXISTS and not ERROR_ALREADY_EXISTS.
354 * Note: RtlNtStatusToDosError is not the subject to blame here.
356 if (Status
== STATUS_OBJECT_NAME_COLLISION
&&
357 dwCreationDisposition
== FILE_CREATE
)
359 SetLastError( ERROR_FILE_EXISTS
);
361 else if (Status
== STATUS_FILE_IS_A_DIRECTORY
&&
364 SetLastError(ERROR_PATH_NOT_FOUND
);
368 BaseSetLastNTError (Status
);
371 return INVALID_HANDLE_VALUE
;
375 create with OPEN_ALWAYS (FILE_OPEN_IF) returns info = FILE_OPENED or FILE_CREATED
376 create with CREATE_ALWAYS (FILE_OVERWRITE_IF) returns info = FILE_OVERWRITTEN or FILE_CREATED
378 if (dwCreationDisposition
== FILE_OPEN_IF
)
380 SetLastError(IoStatusBlock
.Information
== FILE_OPENED
? ERROR_ALREADY_EXISTS
: ERROR_SUCCESS
);
382 else if (dwCreationDisposition
== FILE_OVERWRITE_IF
)
384 SetLastError(IoStatusBlock
.Information
== FILE_OVERWRITTEN
? ERROR_ALREADY_EXISTS
: ERROR_SUCCESS
);
388 SetLastError(ERROR_SUCCESS
);
398 OpenFile(LPCSTR lpFileName
,
399 LPOFSTRUCT lpReOpenBuff
,
402 OBJECT_ATTRIBUTES ObjectAttributes
;
403 IO_STATUS_BLOCK IoStatusBlock
;
404 UNICODE_STRING FileNameString
;
405 UNICODE_STRING FileNameU
;
406 ANSI_STRING FileName
;
407 WCHAR PathNameW
[MAX_PATH
];
408 HANDLE FileHandle
= NULL
;
413 TRACE("OpenFile('%s', lpReOpenBuff %p, uStyle %x)\n", lpFileName
, lpReOpenBuff
, uStyle
);
415 if (lpReOpenBuff
== NULL
)
420 lpReOpenBuff
->nErrCode
= 0;
422 if (uStyle
& OF_REOPEN
) lpFileName
= lpReOpenBuff
->szPathName
;
429 if (!GetFullPathNameA(lpFileName
,
430 sizeof(lpReOpenBuff
->szPathName
),
431 lpReOpenBuff
->szPathName
,
434 lpReOpenBuff
->nErrCode
= (WORD
)GetLastError();
438 if (uStyle
& OF_PARSE
)
440 lpReOpenBuff
->fFixedDisk
= (GetDriveTypeA(lpReOpenBuff
->szPathName
) != DRIVE_REMOVABLE
);
441 TRACE("(%s): OF_PARSE, res = '%s'\n", lpFileName
, lpReOpenBuff
->szPathName
);
445 if ((uStyle
& OF_EXIST
) && !(uStyle
& OF_CREATE
))
447 DWORD dwAttributes
= GetFileAttributesA(lpReOpenBuff
->szPathName
);
449 switch (dwAttributes
)
451 case INVALID_FILE_ATTRIBUTES
: /* File does not exist */
452 SetLastError(ERROR_FILE_NOT_FOUND
);
453 lpReOpenBuff
->nErrCode
= (WORD
) ERROR_FILE_NOT_FOUND
;
456 case FILE_ATTRIBUTE_DIRECTORY
:
457 SetLastError(ERROR_ACCESS_DENIED
);
458 lpReOpenBuff
->nErrCode
= (WORD
) ERROR_ACCESS_DENIED
;
462 lpReOpenBuff
->cBytes
= sizeof(OFSTRUCT
);
466 lpReOpenBuff
->cBytes
= sizeof(OFSTRUCT
);
467 if ((uStyle
& OF_CREATE
) == OF_CREATE
)
470 switch (uStyle
& 0x70)
472 case OF_SHARE_EXCLUSIVE
: Sharing
= 0; break;
473 case OF_SHARE_DENY_WRITE
: Sharing
= FILE_SHARE_READ
; break;
474 case OF_SHARE_DENY_READ
: Sharing
= FILE_SHARE_WRITE
; break;
475 case OF_SHARE_DENY_NONE
:
476 case OF_SHARE_COMPAT
:
478 Sharing
= FILE_SHARE_READ
| FILE_SHARE_WRITE
;
480 return (HFILE
) CreateFileA (lpFileName
,
481 GENERIC_READ
| GENERIC_WRITE
,
485 FILE_ATTRIBUTE_NORMAL
,
489 RtlInitAnsiString (&FileName
, (LPSTR
)lpFileName
);
491 /* convert ansi (or oem) string to unicode */
493 RtlAnsiStringToUnicodeString (&FileNameU
, &FileName
, TRUE
);
495 RtlOemStringToUnicodeString (&FileNameU
, &FileName
, TRUE
);
497 Len
= SearchPathW (NULL
,
504 RtlFreeUnicodeString(&FileNameU
);
506 if (Len
== 0 || Len
> OFS_MAXPATHNAME
)
508 lpReOpenBuff
->nErrCode
= (WORD
)GetLastError();
509 return (HFILE
)INVALID_HANDLE_VALUE
;
512 if (uStyle
& OF_DELETE
)
514 if (!DeleteFileW(PathNameW
))
516 lpReOpenBuff
->nErrCode
= (WORD
)GetLastError();
519 TRACE("(%s): OF_DELETE return = OK\n", lpFileName
);
523 FileName
.Buffer
= lpReOpenBuff
->szPathName
;
525 FileName
.MaximumLength
= OFS_MAXPATHNAME
;
527 RtlInitUnicodeString(&FileNameU
, PathNameW
);
529 /* convert unicode string to ansi (or oem) */
531 RtlUnicodeStringToAnsiString (&FileName
, &FileNameU
, FALSE
);
533 RtlUnicodeStringToOemString (&FileName
, &FileNameU
, FALSE
);
535 if (!RtlDosPathNameToNtPathName_U (PathNameW
,
540 return (HFILE
)INVALID_HANDLE_VALUE
;
544 // FILE_NO_INTERMEDIATE_BUFFERING
546 ObjectAttributes
.Length
= sizeof(OBJECT_ATTRIBUTES
);
547 ObjectAttributes
.RootDirectory
= NULL
;
548 ObjectAttributes
.ObjectName
= &FileNameString
;
549 ObjectAttributes
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_INHERIT
;
550 ObjectAttributes
.SecurityDescriptor
= NULL
;
551 ObjectAttributes
.SecurityQualityOfService
= NULL
;
553 errCode
= NtOpenFile (&FileHandle
,
554 GENERIC_READ
| SYNCHRONIZE
,
558 FILE_NON_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
560 RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameString
.Buffer
);
562 lpReOpenBuff
->nErrCode
= (WORD
)RtlNtStatusToDosError(errCode
);
564 if (!NT_SUCCESS(errCode
))
566 BaseSetLastNTError (errCode
);
567 return (HFILE
)INVALID_HANDLE_VALUE
;
570 if (uStyle
& OF_EXIST
)
576 return (HFILE
)FileHandle
;
584 OpenDataFile(HANDLE hFile
, DWORD dwUnused
)
595 ReOpenFile(IN HANDLE hOriginalFile
,
596 IN DWORD dwDesiredAccess
,
597 IN DWORD dwShareMode
,
601 return INVALID_HANDLE_VALUE
;