1 /* $Id: create.c 54326 2011-11-07 00:18:13Z ion $
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)
10 * Removed use of SearchPath (not used by Windows)
11 * 18/08/2002: CreateFileW mess cleaned up (KJK::Hyperion)
12 * 24/08/2002: removed superfluous DPRINTs (KJK::Hyperion)
15 /* INCLUDES *****************************************************************/
22 DEBUG_CHANNEL(kernel32file
);
25 #define SYMLINK_FLAG_RELATIVE 1
27 typedef struct _REPARSE_DATA_BUFFER
{
29 USHORT ReparseDataLength
;
33 USHORT SubstituteNameOffset
;
34 USHORT SubstituteNameLength
;
35 USHORT PrintNameOffset
;
36 USHORT PrintNameLength
;
39 } SymbolicLinkReparseBuffer
;
41 USHORT SubstituteNameOffset
;
42 USHORT SubstituteNameLength
;
43 USHORT PrintNameOffset
;
44 USHORT PrintNameLength
;
46 } MountPointReparseBuffer
;
49 } GenericReparseBuffer
;
51 } REPARSE_DATA_BUFFER
, *PREPARSE_DATA_BUFFER
;
53 #define REPARSE_DATA_BUFFER_HEADER_SIZE FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer)
55 /* FUNCTIONS ****************************************************************/
60 HANDLE WINAPI
CreateFileA (LPCSTR lpFileName
,
61 DWORD dwDesiredAccess
,
63 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
64 DWORD dwCreationDisposition
,
65 DWORD dwFlagsAndAttributes
,
71 TRACE("CreateFileA(lpFileName %s)\n",lpFileName
);
73 if (!(FileNameW
= FilenameA2W(lpFileName
, FALSE
)))
74 return INVALID_HANDLE_VALUE
;
76 FileHandle
= CreateFileW (FileNameW
,
80 dwCreationDisposition
,
91 HANDLE WINAPI
CreateFileW (LPCWSTR lpFileName
,
92 DWORD dwDesiredAccess
,
94 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
95 DWORD dwCreationDisposition
,
96 DWORD dwFlagsAndAttributes
,
99 OBJECT_ATTRIBUTES ObjectAttributes
;
100 IO_STATUS_BLOCK IoStatusBlock
;
101 UNICODE_STRING NtPathU
;
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 if (0 == _wcsicmp(L
"CONOUT$", lpFileName
)
146 || 0 == _wcsicmp(L
"CONIN$", lpFileName
))
148 return OpenConsoleW(lpFileName
,
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
)
177 Flags
|= FILE_DELETE_ON_CLOSE
;
179 if(dwFlagsAndAttributes
& FILE_FLAG_BACKUP_SEMANTICS
)
181 if(dwDesiredAccess
& GENERIC_ALL
)
182 Flags
|= FILE_OPEN_FOR_BACKUP_INTENT
| FILE_OPEN_REMOTE_INSTANCE
;
185 if(dwDesiredAccess
& GENERIC_READ
)
186 Flags
|= FILE_OPEN_FOR_BACKUP_INTENT
;
188 if(dwDesiredAccess
& GENERIC_WRITE
)
189 Flags
|= FILE_OPEN_REMOTE_INSTANCE
;
193 Flags
|= FILE_NON_DIRECTORY_FILE
;
195 if(dwFlagsAndAttributes
& FILE_FLAG_OPEN_REPARSE_POINT
)
196 Flags
|= FILE_OPEN_REPARSE_POINT
;
198 if(dwFlagsAndAttributes
& FILE_FLAG_OPEN_NO_RECALL
)
199 Flags
|= FILE_OPEN_NO_RECALL
;
201 FileAttributes
= (dwFlagsAndAttributes
& (FILE_ATTRIBUTE_VALID_FLAGS
& ~FILE_ATTRIBUTE_DIRECTORY
));
203 /* handle may allways be waited on and querying attributes are allways allowed */
204 dwDesiredAccess
|= SYNCHRONIZE
| FILE_READ_ATTRIBUTES
;
206 /* FILE_FLAG_POSIX_SEMANTICS is handled later */
208 /* validate & translate the filename */
209 if (!RtlDosPathNameToNtPathName_U (lpFileName
,
214 WARN("Invalid path\n");
215 SetLastError(ERROR_FILE_NOT_FOUND
);
216 return INVALID_HANDLE_VALUE
;
219 TRACE("NtPathU \'%wZ\'\n", &NtPathU
);
221 if (hTemplateFile
!= NULL
)
223 FILE_EA_INFORMATION EaInformation
;
227 /* try to get the size of the extended attributes, if we fail just continue
228 creating the file without copying the attributes! */
229 Status
= NtQueryInformationFile(hTemplateFile
,
232 sizeof(FILE_EA_INFORMATION
),
234 if (NT_SUCCESS(Status
) && (EaInformation
.EaSize
!= 0))
236 /* there's extended attributes to read, let's give it a try */
237 EaBuffer
= RtlAllocateHeap(RtlGetProcessHeap(),
239 EaInformation
.EaSize
);
240 if (EaBuffer
== NULL
)
242 RtlFreeHeap(RtlGetProcessHeap(),
246 /* the template file handle is valid and has extended attributes,
247 however we seem to lack some memory here. We should fail here! */
248 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
249 return INVALID_HANDLE_VALUE
;
252 Status
= NtQueryEaFile(hTemplateFile
,
255 EaInformation
.EaSize
,
262 if (NT_SUCCESS(Status
))
264 /* we successfully read the extended attributes, break the loop
266 EaLength
= EaInformation
.EaSize
;
271 RtlFreeHeap(RtlGetProcessHeap(),
276 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
278 /* unless we just allocated not enough memory, break the loop
279 and just continue without copying extended attributes */
286 /* we either failed to get the size of the extended attributes or
287 they're empty, just continue as there's no need to copy
294 /* build the object attributes */
295 InitializeObjectAttributes(&ObjectAttributes
,
301 if (lpSecurityAttributes
)
303 if(lpSecurityAttributes
->bInheritHandle
)
304 ObjectAttributes
.Attributes
|= OBJ_INHERIT
;
306 ObjectAttributes
.SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
309 if(!(dwFlagsAndAttributes
& FILE_FLAG_POSIX_SEMANTICS
))
310 ObjectAttributes
.Attributes
|= OBJ_CASE_INSENSITIVE
;
312 /* perform the call */
313 Status
= NtCreateFile (&FileHandle
,
320 dwCreationDisposition
,
325 RtlFreeHeap(RtlGetProcessHeap(),
329 /* free the extended attributes buffer if allocated */
330 if (EaBuffer
!= NULL
)
332 RtlFreeHeap(RtlGetProcessHeap(),
338 if (!NT_SUCCESS(Status
))
340 /* In the case file creation was rejected due to CREATE_NEW flag
341 * was specified and file with that name already exists, correct
342 * last error is ERROR_FILE_EXISTS and not ERROR_ALREADY_EXISTS.
343 * Note: RtlNtStatusToDosError is not the subject to blame here.
345 if (Status
== STATUS_OBJECT_NAME_COLLISION
&&
346 dwCreationDisposition
== FILE_CREATE
)
348 SetLastError( ERROR_FILE_EXISTS
);
352 BaseSetLastNTError (Status
);
355 return INVALID_HANDLE_VALUE
;
359 create with OPEN_ALWAYS (FILE_OPEN_IF) returns info = FILE_OPENED or FILE_CREATED
360 create with CREATE_ALWAYS (FILE_OVERWRITE_IF) returns info = FILE_OVERWRITTEN or FILE_CREATED
362 if (dwCreationDisposition
== FILE_OPEN_IF
)
364 SetLastError(IoStatusBlock
.Information
== FILE_OPENED
? ERROR_ALREADY_EXISTS
: ERROR_SUCCESS
);
366 else if (dwCreationDisposition
== FILE_OVERWRITE_IF
)
368 SetLastError(IoStatusBlock
.Information
== FILE_OVERWRITTEN
? ERROR_ALREADY_EXISTS
: ERROR_SUCCESS
);
372 SetLastError(ERROR_SUCCESS
);
382 OpenFile(LPCSTR lpFileName
,
383 LPOFSTRUCT lpReOpenBuff
,
386 OBJECT_ATTRIBUTES ObjectAttributes
;
387 IO_STATUS_BLOCK IoStatusBlock
;
388 UNICODE_STRING FileNameString
;
389 UNICODE_STRING FileNameU
;
390 ANSI_STRING FileName
;
391 WCHAR PathNameW
[MAX_PATH
];
392 HANDLE FileHandle
= NULL
;
397 TRACE("OpenFile('%s', lpReOpenBuff %x, uStyle %x)\n", lpFileName
, lpReOpenBuff
, uStyle
);
399 if (lpReOpenBuff
== NULL
)
404 lpReOpenBuff
->nErrCode
= 0;
406 if (uStyle
& OF_REOPEN
) lpFileName
= lpReOpenBuff
->szPathName
;
413 if (!GetFullPathNameA(lpFileName
,
414 sizeof(lpReOpenBuff
->szPathName
),
415 lpReOpenBuff
->szPathName
,
418 lpReOpenBuff
->nErrCode
= GetLastError();
422 if (uStyle
& OF_PARSE
)
424 lpReOpenBuff
->fFixedDisk
= (GetDriveTypeA(lpReOpenBuff
->szPathName
) != DRIVE_REMOVABLE
);
425 TRACE("(%s): OF_PARSE, res = '%s'\n", lpFileName
, lpReOpenBuff
->szPathName
);
429 if ((uStyle
& OF_EXIST
) && !(uStyle
& OF_CREATE
))
431 DWORD dwAttributes
= GetFileAttributesA(lpReOpenBuff
->szPathName
);
433 switch (dwAttributes
)
435 case 0xFFFFFFFF: /* File does not exist */
436 SetLastError(ERROR_FILE_NOT_FOUND
);
437 lpReOpenBuff
->nErrCode
= (WORD
) ERROR_FILE_NOT_FOUND
;
440 case FILE_ATTRIBUTE_DIRECTORY
:
441 SetLastError(ERROR_ACCESS_DENIED
);
442 lpReOpenBuff
->nErrCode
= (WORD
) ERROR_ACCESS_DENIED
;
446 lpReOpenBuff
->cBytes
= sizeof(OFSTRUCT
);
450 lpReOpenBuff
->cBytes
= sizeof(OFSTRUCT
);
451 if ((uStyle
& OF_CREATE
) == OF_CREATE
)
454 switch (uStyle
& 0x70)
456 case OF_SHARE_EXCLUSIVE
: Sharing
= 0; break;
457 case OF_SHARE_DENY_WRITE
: Sharing
= FILE_SHARE_READ
; break;
458 case OF_SHARE_DENY_READ
: Sharing
= FILE_SHARE_WRITE
; break;
459 case OF_SHARE_DENY_NONE
:
460 case OF_SHARE_COMPAT
:
462 Sharing
= FILE_SHARE_READ
| FILE_SHARE_WRITE
;
464 return (HFILE
) CreateFileA (lpFileName
,
465 GENERIC_READ
| GENERIC_WRITE
,
469 FILE_ATTRIBUTE_NORMAL
,
473 RtlInitAnsiString (&FileName
, (LPSTR
)lpFileName
);
475 /* convert ansi (or oem) string to unicode */
477 RtlAnsiStringToUnicodeString (&FileNameU
, &FileName
, TRUE
);
479 RtlOemStringToUnicodeString (&FileNameU
, &FileName
, TRUE
);
481 Len
= SearchPathW (NULL
,
488 RtlFreeUnicodeString(&FileNameU
);
490 if (Len
== 0 || Len
> OFS_MAXPATHNAME
)
492 lpReOpenBuff
->nErrCode
= GetLastError();
493 return (HFILE
)INVALID_HANDLE_VALUE
;
496 if (uStyle
& OF_DELETE
)
498 if (!DeleteFileW(PathNameW
))
500 lpReOpenBuff
->nErrCode
= GetLastError();
503 TRACE("(%s): OF_DELETE return = OK\n", lpFileName
);
507 FileName
.Buffer
= lpReOpenBuff
->szPathName
;
509 FileName
.MaximumLength
= OFS_MAXPATHNAME
;
511 RtlInitUnicodeString(&FileNameU
, PathNameW
);
513 /* convert unicode string to ansi (or oem) */
515 RtlUnicodeStringToAnsiString (&FileName
, &FileNameU
, FALSE
);
517 RtlUnicodeStringToOemString (&FileName
, &FileNameU
, FALSE
);
519 if (!RtlDosPathNameToNtPathName_U (PathNameW
,
524 return (HFILE
)INVALID_HANDLE_VALUE
;
528 // FILE_NO_INTERMEDIATE_BUFFERING
530 ObjectAttributes
.Length
= sizeof(OBJECT_ATTRIBUTES
);
531 ObjectAttributes
.RootDirectory
= NULL
;
532 ObjectAttributes
.ObjectName
= &FileNameString
;
533 ObjectAttributes
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_INHERIT
;
534 ObjectAttributes
.SecurityDescriptor
= NULL
;
535 ObjectAttributes
.SecurityQualityOfService
= NULL
;
537 errCode
= NtOpenFile (&FileHandle
,
538 GENERIC_READ
|SYNCHRONIZE
,
542 FILE_NON_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
);
544 RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameString
.Buffer
);
546 lpReOpenBuff
->nErrCode
= RtlNtStatusToDosError(errCode
);
548 if (!NT_SUCCESS(errCode
))
550 BaseSetLastNTError (errCode
);
551 return (HFILE
)INVALID_HANDLE_VALUE
;
554 if (uStyle
& OF_EXIST
)
560 return (HFILE
)FileHandle
;
568 OpenDataFile(HANDLE hFile
, DWORD dwUnused
)
579 ReOpenFile(IN HANDLE hOriginalFile
,
580 IN DWORD dwDesiredAccess
,
581 IN DWORD dwShareMode
,
585 return INVALID_HANDLE_VALUE
;