+++ /dev/null
-/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS system libraries
- * FILE: lib/kernel32/file/create.c
- * PURPOSE: Directory functions
- * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
- * UPDATE HISTORY:
- * Created 01/11/98
- * Removed use of SearchPath (not used by Windows)
- * 18/08/2002: CreateFileW mess cleaned up (KJK::Hyperion)
- * 24/08/2002: removed superfluous DPRINTs (KJK::Hyperion)
- */
-
-/* INCLUDES *****************************************************************/
-
-#include <k32.h>
-#define NDEBUG
-#include <debug.h>
-
-#if DBG
-DEBUG_CHANNEL(kernel32file);
-#endif
-
-#define SYMLINK_FLAG_RELATIVE 1
-
-typedef struct _REPARSE_DATA_BUFFER {
- ULONG ReparseTag;
- USHORT ReparseDataLength;
- USHORT Reserved;
- union {
- struct {
- USHORT SubstituteNameOffset;
- USHORT SubstituteNameLength;
- USHORT PrintNameOffset;
- USHORT PrintNameLength;
- ULONG Flags;
- WCHAR PathBuffer[1];
- } SymbolicLinkReparseBuffer;
- struct {
- USHORT SubstituteNameOffset;
- USHORT SubstituteNameLength;
- USHORT PrintNameOffset;
- USHORT PrintNameLength;
- WCHAR PathBuffer[1];
- } MountPointReparseBuffer;
- struct {
- UCHAR DataBuffer[1];
- } GenericReparseBuffer;
- };
-} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
-
-#define REPARSE_DATA_BUFFER_HEADER_SIZE FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer)
-
-/* FUNCTIONS ****************************************************************/
-
-/*
- * @implemented
- */
-HANDLE WINAPI CreateFileA (LPCSTR lpFileName,
- DWORD dwDesiredAccess,
- DWORD dwShareMode,
- LPSECURITY_ATTRIBUTES lpSecurityAttributes,
- DWORD dwCreationDisposition,
- DWORD dwFlagsAndAttributes,
- HANDLE hTemplateFile)
-{
- PWCHAR FileNameW;
- HANDLE FileHandle;
-
- TRACE("CreateFileA(lpFileName %s)\n",lpFileName);
-
- if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
- return INVALID_HANDLE_VALUE;
-
- FileHandle = CreateFileW (FileNameW,
- dwDesiredAccess,
- dwShareMode,
- lpSecurityAttributes,
- dwCreationDisposition,
- dwFlagsAndAttributes,
- hTemplateFile);
-
- return FileHandle;
-}
-
-
-/*
- * @implemented
- */
-HANDLE WINAPI CreateFileW (LPCWSTR lpFileName,
- DWORD dwDesiredAccess,
- DWORD dwShareMode,
- LPSECURITY_ATTRIBUTES lpSecurityAttributes,
- DWORD dwCreationDisposition,
- DWORD dwFlagsAndAttributes,
- HANDLE hTemplateFile)
-{
- OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK IoStatusBlock;
- UNICODE_STRING NtPathU;
- LPCWSTR pszConsoleFileName;
- HANDLE FileHandle;
- NTSTATUS Status;
- ULONG FileAttributes, Flags = 0;
- PVOID EaBuffer = NULL;
- ULONG EaLength = 0;
-
- if (!lpFileName || !lpFileName[0])
- {
- SetLastError( ERROR_PATH_NOT_FOUND );
- return INVALID_HANDLE_VALUE;
- }
-
- TRACE("CreateFileW(lpFileName %S)\n",lpFileName);
-
- /* validate & translate the creation disposition */
- switch (dwCreationDisposition)
- {
- case CREATE_NEW:
- dwCreationDisposition = FILE_CREATE;
- break;
-
- case CREATE_ALWAYS:
- dwCreationDisposition = FILE_OVERWRITE_IF;
- break;
-
- case OPEN_EXISTING:
- dwCreationDisposition = FILE_OPEN;
- break;
-
- case OPEN_ALWAYS:
- dwCreationDisposition = FILE_OPEN_IF;
- break;
-
- case TRUNCATE_EXISTING:
- dwCreationDisposition = FILE_OVERWRITE;
- break;
-
- default:
- SetLastError(ERROR_INVALID_PARAMETER);
- return (INVALID_HANDLE_VALUE);
- }
-
- /* check for console input/output */
- pszConsoleFileName = IntCheckForConsoleFileName(lpFileName, dwDesiredAccess);
- if (pszConsoleFileName)
- {
- return OpenConsoleW(pszConsoleFileName,
- dwDesiredAccess,
- lpSecurityAttributes ? lpSecurityAttributes->bInheritHandle : FALSE,
- FILE_SHARE_READ | FILE_SHARE_WRITE);
- }
-
- /* validate & translate the flags */
-
- /* translate the flags that need no validation */
- if (!(dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
- {
- /* yes, nonalert is correct! apc's are not delivered
- while waiting for file io to complete */
- Flags |= FILE_SYNCHRONOUS_IO_NONALERT;
- }
-
- if(dwFlagsAndAttributes & FILE_FLAG_WRITE_THROUGH)
- Flags |= FILE_WRITE_THROUGH;
-
- if(dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING)
- Flags |= FILE_NO_INTERMEDIATE_BUFFERING;
-
- if(dwFlagsAndAttributes & FILE_FLAG_RANDOM_ACCESS)
- Flags |= FILE_RANDOM_ACCESS;
-
- if(dwFlagsAndAttributes & FILE_FLAG_SEQUENTIAL_SCAN)
- Flags |= FILE_SEQUENTIAL_ONLY;
-
- if(dwFlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE)
- {
- Flags |= FILE_DELETE_ON_CLOSE;
- dwDesiredAccess |= DELETE;
- }
-
- if(dwFlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS)
- {
- if(dwDesiredAccess & GENERIC_ALL)
- Flags |= FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REMOTE_INSTANCE;
- else
- {
- if(dwDesiredAccess & GENERIC_READ)
- Flags |= FILE_OPEN_FOR_BACKUP_INTENT;
-
- if(dwDesiredAccess & GENERIC_WRITE)
- Flags |= FILE_OPEN_REMOTE_INSTANCE;
- }
- }
- else
- Flags |= FILE_NON_DIRECTORY_FILE;
-
- if(dwFlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT)
- Flags |= FILE_OPEN_REPARSE_POINT;
-
- if(dwFlagsAndAttributes & FILE_FLAG_OPEN_NO_RECALL)
- Flags |= FILE_OPEN_NO_RECALL;
-
- FileAttributes = (dwFlagsAndAttributes & (FILE_ATTRIBUTE_VALID_FLAGS & ~FILE_ATTRIBUTE_DIRECTORY));
-
- /* handle may always be waited on and querying attributes are always allowed */
- dwDesiredAccess |= SYNCHRONIZE | FILE_READ_ATTRIBUTES;
-
- /* FILE_FLAG_POSIX_SEMANTICS is handled later */
-
- /* validate & translate the filename */
- if (!RtlDosPathNameToNtPathName_U (lpFileName,
- &NtPathU,
- NULL,
- NULL))
- {
- WARN("Invalid path\n");
- SetLastError(ERROR_FILE_NOT_FOUND);
- return INVALID_HANDLE_VALUE;
- }
-
- TRACE("NtPathU \'%wZ\'\n", &NtPathU);
-
- if (hTemplateFile != NULL)
- {
- FILE_EA_INFORMATION EaInformation;
-
- for (;;)
- {
- /* try to get the size of the extended attributes, if we fail just continue
- creating the file without copying the attributes! */
- Status = NtQueryInformationFile(hTemplateFile,
- &IoStatusBlock,
- &EaInformation,
- sizeof(FILE_EA_INFORMATION),
- FileEaInformation);
- if (NT_SUCCESS(Status) && (EaInformation.EaSize != 0))
- {
- /* there's extended attributes to read, let's give it a try */
- EaBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
- 0,
- EaInformation.EaSize);
- if (EaBuffer == NULL)
- {
- RtlFreeHeap(RtlGetProcessHeap(),
- 0,
- NtPathU.Buffer);
-
- /* the template file handle is valid and has extended attributes,
- however we seem to lack some memory here. We should fail here! */
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return INVALID_HANDLE_VALUE;
- }
-
- Status = NtQueryEaFile(hTemplateFile,
- &IoStatusBlock,
- EaBuffer,
- EaInformation.EaSize,
- FALSE,
- NULL,
- 0,
- NULL,
- TRUE);
-
- if (NT_SUCCESS(Status))
- {
- /* we successfully read the extended attributes, break the loop
- and continue */
- EaLength = EaInformation.EaSize;
- break;
- }
- else
- {
- RtlFreeHeap(RtlGetProcessHeap(),
- 0,
- EaBuffer);
- EaBuffer = NULL;
-
- if (Status != STATUS_BUFFER_TOO_SMALL)
- {
- /* unless we just allocated not enough memory, break the loop
- and just continue without copying extended attributes */
- break;
- }
- }
- }
- else
- {
- /* we either failed to get the size of the extended attributes or
- they're empty, just continue as there's no need to copy
- attributes */
- break;
- }
- }
- }
-
- /* build the object attributes */
- InitializeObjectAttributes(&ObjectAttributes,
- &NtPathU,
- 0,
- NULL,
- NULL);
-
- if (lpSecurityAttributes)
- {
- if(lpSecurityAttributes->bInheritHandle)
- ObjectAttributes.Attributes |= OBJ_INHERIT;
-
- ObjectAttributes.SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
- }
-
- if(!(dwFlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS))
- ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
-
- /* perform the call */
- Status = NtCreateFile (&FileHandle,
- dwDesiredAccess,
- &ObjectAttributes,
- &IoStatusBlock,
- NULL,
- FileAttributes,
- dwShareMode,
- dwCreationDisposition,
- Flags,
- EaBuffer,
- EaLength);
-
- RtlFreeHeap(RtlGetProcessHeap(),
- 0,
- NtPathU.Buffer);
-
- /* free the extended attributes buffer if allocated */
- if (EaBuffer != NULL)
- {
- RtlFreeHeap(RtlGetProcessHeap(),
- 0,
- EaBuffer);
- }
-
- /* error */
- if (!NT_SUCCESS(Status))
- {
- /* In the case file creation was rejected due to CREATE_NEW flag
- * was specified and file with that name already exists, correct
- * last error is ERROR_FILE_EXISTS and not ERROR_ALREADY_EXISTS.
- * Note: RtlNtStatusToDosError is not the subject to blame here.
- */
- if (Status == STATUS_OBJECT_NAME_COLLISION &&
- dwCreationDisposition == FILE_CREATE)
- {
- SetLastError( ERROR_FILE_EXISTS );
- }
- else
- {
- BaseSetLastNTError (Status);
- }
-
- return INVALID_HANDLE_VALUE;
- }
-
- /*
- create with OPEN_ALWAYS (FILE_OPEN_IF) returns info = FILE_OPENED or FILE_CREATED
- create with CREATE_ALWAYS (FILE_OVERWRITE_IF) returns info = FILE_OVERWRITTEN or FILE_CREATED
- */
- if (dwCreationDisposition == FILE_OPEN_IF)
- {
- SetLastError(IoStatusBlock.Information == FILE_OPENED ? ERROR_ALREADY_EXISTS : ERROR_SUCCESS);
- }
- else if (dwCreationDisposition == FILE_OVERWRITE_IF)
- {
- SetLastError(IoStatusBlock.Information == FILE_OVERWRITTEN ? ERROR_ALREADY_EXISTS : ERROR_SUCCESS);
- }
- else
- {
- SetLastError(ERROR_SUCCESS);
- }
-
- return FileHandle;
-}
-
-/*
- * @implemented
- */
-HFILE WINAPI
-OpenFile(LPCSTR lpFileName,
- LPOFSTRUCT lpReOpenBuff,
- UINT uStyle)
-{
- OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK IoStatusBlock;
- UNICODE_STRING FileNameString;
- UNICODE_STRING FileNameU;
- ANSI_STRING FileName;
- WCHAR PathNameW[MAX_PATH];
- HANDLE FileHandle = NULL;
- NTSTATUS errCode;
- PWCHAR FilePart;
- ULONG Len;
-
- TRACE("OpenFile('%s', lpReOpenBuff %p, uStyle %x)\n", lpFileName, lpReOpenBuff, uStyle);
-
- if (lpReOpenBuff == NULL)
- {
- return HFILE_ERROR;
- }
-
- lpReOpenBuff->nErrCode = 0;
-
- if (uStyle & OF_REOPEN) lpFileName = lpReOpenBuff->szPathName;
-
- if (!lpFileName)
- {
- return HFILE_ERROR;
- }
-
- if (!GetFullPathNameA(lpFileName,
- sizeof(lpReOpenBuff->szPathName),
- lpReOpenBuff->szPathName,
- NULL))
- {
- lpReOpenBuff->nErrCode = (WORD)GetLastError();
- return HFILE_ERROR;
- }
-
- if (uStyle & OF_PARSE)
- {
- lpReOpenBuff->fFixedDisk = (GetDriveTypeA(lpReOpenBuff->szPathName) != DRIVE_REMOVABLE);
- TRACE("(%s): OF_PARSE, res = '%s'\n", lpFileName, lpReOpenBuff->szPathName);
- return 0;
- }
-
- if ((uStyle & OF_EXIST) && !(uStyle & OF_CREATE))
- {
- DWORD dwAttributes = GetFileAttributesA(lpReOpenBuff->szPathName);
-
- switch (dwAttributes)
- {
- case 0xFFFFFFFF: /* File does not exist */
- SetLastError(ERROR_FILE_NOT_FOUND);
- lpReOpenBuff->nErrCode = (WORD) ERROR_FILE_NOT_FOUND;
- return -1;
-
- case FILE_ATTRIBUTE_DIRECTORY:
- SetLastError(ERROR_ACCESS_DENIED);
- lpReOpenBuff->nErrCode = (WORD) ERROR_ACCESS_DENIED;
- return -1;
-
- default:
- lpReOpenBuff->cBytes = sizeof(OFSTRUCT);
- return 1;
- }
- }
- lpReOpenBuff->cBytes = sizeof(OFSTRUCT);
- if ((uStyle & OF_CREATE) == OF_CREATE)
- {
- DWORD Sharing;
- switch (uStyle & 0x70)
- {
- case OF_SHARE_EXCLUSIVE: Sharing = 0; break;
- case OF_SHARE_DENY_WRITE: Sharing = FILE_SHARE_READ; break;
- case OF_SHARE_DENY_READ: Sharing = FILE_SHARE_WRITE; break;
- case OF_SHARE_DENY_NONE:
- case OF_SHARE_COMPAT:
- default:
- Sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
- }
- return (HFILE) CreateFileA (lpFileName,
- GENERIC_READ | GENERIC_WRITE,
- Sharing,
- NULL,
- CREATE_ALWAYS,
- FILE_ATTRIBUTE_NORMAL,
- 0);
- }
-
- RtlInitAnsiString (&FileName, (LPSTR)lpFileName);
-
- /* convert ansi (or oem) string to unicode */
- if (bIsFileApiAnsi)
- RtlAnsiStringToUnicodeString (&FileNameU, &FileName, TRUE);
- else
- RtlOemStringToUnicodeString (&FileNameU, &FileName, TRUE);
-
- Len = SearchPathW (NULL,
- FileNameU.Buffer,
- NULL,
- OFS_MAXPATHNAME,
- PathNameW,
- &FilePart);
-
- RtlFreeUnicodeString(&FileNameU);
-
- if (Len == 0 || Len > OFS_MAXPATHNAME)
- {
- lpReOpenBuff->nErrCode = (WORD)GetLastError();
- return (HFILE)INVALID_HANDLE_VALUE;
- }
-
- if (uStyle & OF_DELETE)
- {
- if (!DeleteFileW(PathNameW))
- {
- lpReOpenBuff->nErrCode = (WORD)GetLastError();
- return HFILE_ERROR;
- }
- TRACE("(%s): OF_DELETE return = OK\n", lpFileName);
- return TRUE;
- }
-
- FileName.Buffer = lpReOpenBuff->szPathName;
- FileName.Length = 0;
- FileName.MaximumLength = OFS_MAXPATHNAME;
-
- RtlInitUnicodeString(&FileNameU, PathNameW);
-
- /* convert unicode string to ansi (or oem) */
- if (bIsFileApiAnsi)
- RtlUnicodeStringToAnsiString (&FileName, &FileNameU, FALSE);
- else
- RtlUnicodeStringToOemString (&FileName, &FileNameU, FALSE);
-
- if (!RtlDosPathNameToNtPathName_U (PathNameW,
- &FileNameString,
- NULL,
- NULL))
- {
- return (HFILE)INVALID_HANDLE_VALUE;
- }
-
- // FILE_SHARE_READ
- // FILE_NO_INTERMEDIATE_BUFFERING
-
- ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
- ObjectAttributes.RootDirectory = NULL;
- ObjectAttributes.ObjectName = &FileNameString;
- ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT;
- ObjectAttributes.SecurityDescriptor = NULL;
- ObjectAttributes.SecurityQualityOfService = NULL;
-
- errCode = NtOpenFile (&FileHandle,
- GENERIC_READ | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ,
- FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
-
- RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameString.Buffer);
-
- lpReOpenBuff->nErrCode = (WORD)RtlNtStatusToDosError(errCode);
-
- if (!NT_SUCCESS(errCode))
- {
- BaseSetLastNTError (errCode);
- return (HFILE)INVALID_HANDLE_VALUE;
- }
-
- if (uStyle & OF_EXIST)
- {
- NtClose(FileHandle);
- return (HFILE)1;
- }
-
- return (HFILE)FileHandle;
-}
-
-/*
- * @unimplemented
- */
-BOOL
-WINAPI
-OpenDataFile(HANDLE hFile, DWORD dwUnused)
-{
- STUB;
- return FALSE;
-}
-
-/*
- * @unimplemented
- */
-HANDLE
-WINAPI
-ReOpenFile(IN HANDLE hOriginalFile,
- IN DWORD dwDesiredAccess,
- IN DWORD dwShareMode,
- IN DWORD dwFlags)
-{
- STUB;
- return INVALID_HANDLE_VALUE;
-}
-
-/* EOF */