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
;
108 if (!lpFileName
|| !lpFileName
[0])
110 SetLastError( ERROR_PATH_NOT_FOUND
);
111 return INVALID_HANDLE_VALUE
;
114 TRACE("CreateFileW(lpFileName %S)\n",lpFileName
);
116 /* validate & translate the creation disposition */
117 switch (dwCreationDisposition
)
120 dwCreationDisposition
= FILE_CREATE
;
124 dwCreationDisposition
= FILE_OVERWRITE_IF
;
128 dwCreationDisposition
= FILE_OPEN
;
132 dwCreationDisposition
= FILE_OPEN_IF
;
135 case TRUNCATE_EXISTING
:
136 dwCreationDisposition
= FILE_OVERWRITE
;
140 SetLastError(ERROR_INVALID_PARAMETER
);
141 return (INVALID_HANDLE_VALUE
);
144 /* check for console input/output */
145 pszConsoleFileName
= IntCheckForConsoleFileName(lpFileName
, dwDesiredAccess
);
146 if (pszConsoleFileName
)
148 return OpenConsoleW(pszConsoleFileName
,
150 lpSecurityAttributes
? lpSecurityAttributes
->bInheritHandle
: FALSE
,
151 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
154 /* validate & translate the flags */
156 /* translate the flags that need no validation */
157 if (!(dwFlagsAndAttributes
& FILE_FLAG_OVERLAPPED
))
159 /* yes, nonalert is correct! apc's are not delivered
160 while waiting for file io to complete */
161 Flags
|= FILE_SYNCHRONOUS_IO_NONALERT
;
164 if(dwFlagsAndAttributes
& FILE_FLAG_WRITE_THROUGH
)
165 Flags
|= FILE_WRITE_THROUGH
;
167 if(dwFlagsAndAttributes
& FILE_FLAG_NO_BUFFERING
)
168 Flags
|= FILE_NO_INTERMEDIATE_BUFFERING
;
170 if(dwFlagsAndAttributes
& FILE_FLAG_RANDOM_ACCESS
)
171 Flags
|= FILE_RANDOM_ACCESS
;
173 if(dwFlagsAndAttributes
& FILE_FLAG_SEQUENTIAL_SCAN
)
174 Flags
|= FILE_SEQUENTIAL_ONLY
;
176 if(dwFlagsAndAttributes
& FILE_FLAG_DELETE_ON_CLOSE
)
178 Flags
|= FILE_DELETE_ON_CLOSE
;
179 dwDesiredAccess
|= DELETE
;
182 if(dwFlagsAndAttributes
& FILE_FLAG_BACKUP_SEMANTICS
)
184 if(dwDesiredAccess
& GENERIC_ALL
)
185 Flags
|= FILE_OPEN_FOR_BACKUP_INTENT
| FILE_OPEN_REMOTE_INSTANCE
;
188 if(dwDesiredAccess
& GENERIC_READ
)
189 Flags
|= FILE_OPEN_FOR_BACKUP_INTENT
;
191 if(dwDesiredAccess
& GENERIC_WRITE
)
192 Flags
|= FILE_OPEN_REMOTE_INSTANCE
;
196 Flags
|= FILE_NON_DIRECTORY_FILE
;
198 if(dwFlagsAndAttributes
& FILE_FLAG_OPEN_REPARSE_POINT
)
199 Flags
|= FILE_OPEN_REPARSE_POINT
;
201 if(dwFlagsAndAttributes
& FILE_FLAG_OPEN_NO_RECALL
)
202 Flags
|= FILE_OPEN_NO_RECALL
;
204 FileAttributes
= (dwFlagsAndAttributes
& (FILE_ATTRIBUTE_VALID_FLAGS
& ~FILE_ATTRIBUTE_DIRECTORY
));
206 /* handle may always be waited on and querying attributes are always allowed */
207 dwDesiredAccess
|= SYNCHRONIZE
| FILE_READ_ATTRIBUTES
;
209 /* FILE_FLAG_POSIX_SEMANTICS is handled later */
211 /* validate & translate the filename */
212 if (!RtlDosPathNameToNtPathName_U (lpFileName
,
217 WARN("Invalid path\n");
218 SetLastError(ERROR_FILE_NOT_FOUND
);
219 return INVALID_HANDLE_VALUE
;
222 TRACE("NtPathU \'%wZ\'\n", &NtPathU
);
224 if (hTemplateFile
!= NULL
)
226 FILE_EA_INFORMATION EaInformation
;
230 /* try to get the size of the extended attributes, if we fail just continue
231 creating the file without copying the attributes! */
232 Status
= NtQueryInformationFile(hTemplateFile
,
235 sizeof(FILE_EA_INFORMATION
),
237 if (NT_SUCCESS(Status
) && (EaInformation
.EaSize
!= 0))
239 /* there's extended attributes to read, let's give it a try */
240 EaBuffer
= RtlAllocateHeap(RtlGetProcessHeap(),
242 EaInformation
.EaSize
);
243 if (EaBuffer
== NULL
)
245 RtlFreeHeap(RtlGetProcessHeap(),
249 /* the template file handle is valid and has extended attributes,
250 however we seem to lack some memory here. We should fail here! */
251 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
252 return INVALID_HANDLE_VALUE
;
255 Status
= NtQueryEaFile(hTemplateFile
,
258 EaInformation
.EaSize
,
265 if (NT_SUCCESS(Status
))
267 /* we successfully read the extended attributes, break the loop
269 EaLength
= EaInformation
.EaSize
;
274 RtlFreeHeap(RtlGetProcessHeap(),
279 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
281 /* unless we just allocated not enough memory, break the loop
282 and just continue without copying extended attributes */
289 /* we either failed to get the size of the extended attributes or
290 they're empty, just continue as there's no need to copy
297 /* build the object attributes */
298 InitializeObjectAttributes(&ObjectAttributes
,
304 if (lpSecurityAttributes
)
306 if(lpSecurityAttributes
->bInheritHandle
)
307 ObjectAttributes
.Attributes
|= OBJ_INHERIT
;
309 ObjectAttributes
.SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
312 if(!(dwFlagsAndAttributes
& FILE_FLAG_POSIX_SEMANTICS
))
313 ObjectAttributes
.Attributes
|= OBJ_CASE_INSENSITIVE
;
315 /* perform the call */
316 Status
= NtCreateFile (&FileHandle
,
323 dwCreationDisposition
,
328 RtlFreeHeap(RtlGetProcessHeap(),
332 /* free the extended attributes buffer if allocated */
333 if (EaBuffer
!= NULL
)
335 RtlFreeHeap(RtlGetProcessHeap(),
341 if (!NT_SUCCESS(Status
))
343 /* In the case file creation was rejected due to CREATE_NEW flag
344 * was specified and file with that name already exists, correct
345 * last error is ERROR_FILE_EXISTS and not ERROR_ALREADY_EXISTS.
346 * Note: RtlNtStatusToDosError is not the subject to blame here.
348 if (Status
== STATUS_OBJECT_NAME_COLLISION
&&
349 dwCreationDisposition
== FILE_CREATE
)
351 SetLastError( ERROR_FILE_EXISTS
);
355 BaseSetLastNTError (Status
);
358 return INVALID_HANDLE_VALUE
;
362 create with OPEN_ALWAYS (FILE_OPEN_IF) returns info = FILE_OPENED or FILE_CREATED
363 create with CREATE_ALWAYS (FILE_OVERWRITE_IF) returns info = FILE_OVERWRITTEN or FILE_CREATED
365 if (dwCreationDisposition
== FILE_OPEN_IF
)
367 SetLastError(IoStatusBlock
.Information
== FILE_OPENED
? ERROR_ALREADY_EXISTS
: ERROR_SUCCESS
);
369 else if (dwCreationDisposition
== FILE_OVERWRITE_IF
)
371 SetLastError(IoStatusBlock
.Information
== FILE_OVERWRITTEN
? ERROR_ALREADY_EXISTS
: ERROR_SUCCESS
);
375 SetLastError(ERROR_SUCCESS
);
385 OpenFile(LPCSTR lpFileName
,
386 LPOFSTRUCT lpReOpenBuff
,
389 OBJECT_ATTRIBUTES ObjectAttributes
;
390 IO_STATUS_BLOCK IoStatusBlock
;
391 UNICODE_STRING FileNameString
;
392 UNICODE_STRING FileNameU
;
393 ANSI_STRING FileName
;
394 WCHAR PathNameW
[MAX_PATH
];
395 HANDLE FileHandle
= NULL
;
400 TRACE("OpenFile('%s', lpReOpenBuff %p, uStyle %x)\n", lpFileName
, lpReOpenBuff
, uStyle
);
402 if (lpReOpenBuff
== NULL
)
407 lpReOpenBuff
->nErrCode
= 0;
409 if (uStyle
& OF_REOPEN
) lpFileName
= lpReOpenBuff
->szPathName
;
416 if (!GetFullPathNameA(lpFileName
,
417 sizeof(lpReOpenBuff
->szPathName
),
418 lpReOpenBuff
->szPathName
,
421 lpReOpenBuff
->nErrCode
= (WORD
)GetLastError();
425 if (uStyle
& OF_PARSE
)
427 lpReOpenBuff
->fFixedDisk
= (GetDriveTypeA(lpReOpenBuff
->szPathName
) != DRIVE_REMOVABLE
);
428 TRACE("(%s): OF_PARSE, res = '%s'\n", lpFileName
, lpReOpenBuff
->szPathName
);
432 if ((uStyle
& OF_EXIST
) && !(uStyle
& OF_CREATE
))
434 DWORD dwAttributes
= GetFileAttributesA(lpReOpenBuff
->szPathName
);
436 switch (dwAttributes
)
438 case INVALID_FILE_ATTRIBUTES
: /* File does not exist */
439 SetLastError(ERROR_FILE_NOT_FOUND
);
440 lpReOpenBuff
->nErrCode
= (WORD
) ERROR_FILE_NOT_FOUND
;
443 case FILE_ATTRIBUTE_DIRECTORY
:
444 SetLastError(ERROR_ACCESS_DENIED
);
445 lpReOpenBuff
->nErrCode
= (WORD
) ERROR_ACCESS_DENIED
;
449 lpReOpenBuff
->cBytes
= sizeof(OFSTRUCT
);
453 lpReOpenBuff
->cBytes
= sizeof(OFSTRUCT
);
454 if ((uStyle
& OF_CREATE
) == OF_CREATE
)
457 switch (uStyle
& 0x70)
459 case OF_SHARE_EXCLUSIVE
: Sharing
= 0; break;
460 case OF_SHARE_DENY_WRITE
: Sharing
= FILE_SHARE_READ
; break;
461 case OF_SHARE_DENY_READ
: Sharing
= FILE_SHARE_WRITE
; break;
462 case OF_SHARE_DENY_NONE
:
463 case OF_SHARE_COMPAT
:
465 Sharing
= FILE_SHARE_READ
| FILE_SHARE_WRITE
;
467 return (HFILE
) CreateFileA (lpFileName
,
468 GENERIC_READ
| GENERIC_WRITE
,
472 FILE_ATTRIBUTE_NORMAL
,
476 RtlInitAnsiString (&FileName
, (LPSTR
)lpFileName
);
478 /* convert ansi (or oem) string to unicode */
480 RtlAnsiStringToUnicodeString (&FileNameU
, &FileName
, TRUE
);
482 RtlOemStringToUnicodeString (&FileNameU
, &FileName
, TRUE
);
484 Len
= SearchPathW (NULL
,
491 RtlFreeUnicodeString(&FileNameU
);
493 if (Len
== 0 || Len
> OFS_MAXPATHNAME
)
495 lpReOpenBuff
->nErrCode
= (WORD
)GetLastError();
496 return (HFILE
)INVALID_HANDLE_VALUE
;
499 if (uStyle
& OF_DELETE
)
501 if (!DeleteFileW(PathNameW
))
503 lpReOpenBuff
->nErrCode
= (WORD
)GetLastError();
506 TRACE("(%s): OF_DELETE return = OK\n", lpFileName
);
510 FileName
.Buffer
= lpReOpenBuff
->szPathName
;
512 FileName
.MaximumLength
= OFS_MAXPATHNAME
;
514 RtlInitUnicodeString(&FileNameU
, PathNameW
);
516 /* convert unicode string to ansi (or oem) */
518 RtlUnicodeStringToAnsiString (&FileName
, &FileNameU
, FALSE
);
520 RtlUnicodeStringToOemString (&FileName
, &FileNameU
, FALSE
);
522 if (!RtlDosPathNameToNtPathName_U (PathNameW
,
527 return (HFILE
)INVALID_HANDLE_VALUE
;
531 // FILE_NO_INTERMEDIATE_BUFFERING
533 ObjectAttributes
.Length
= sizeof(OBJECT_ATTRIBUTES
);
534 ObjectAttributes
.RootDirectory
= NULL
;
535 ObjectAttributes
.ObjectName
= &FileNameString
;
536 ObjectAttributes
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_INHERIT
;
537 ObjectAttributes
.SecurityDescriptor
= NULL
;
538 ObjectAttributes
.SecurityQualityOfService
= NULL
;
540 errCode
= NtOpenFile (&FileHandle
,
541 GENERIC_READ
| SYNCHRONIZE
,
545 FILE_NON_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
547 RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameString
.Buffer
);
549 lpReOpenBuff
->nErrCode
= (WORD
)RtlNtStatusToDosError(errCode
);
551 if (!NT_SUCCESS(errCode
))
553 BaseSetLastNTError (errCode
);
554 return (HFILE
)INVALID_HANDLE_VALUE
;
557 if (uStyle
& OF_EXIST
)
563 return (HFILE
)FileHandle
;
571 OpenDataFile(HANDLE hFile
, DWORD dwUnused
)
582 ReOpenFile(IN HANDLE hOriginalFile
,
583 IN DWORD dwDesiredAccess
,
584 IN DWORD dwShareMode
,
588 return INVALID_HANDLE_VALUE
;