Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries * FILE: dll/win32/kernel32/client/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 DBGDEBUG_CHANNEL(kernel32file);#endif
/* 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; BOOLEAN TrailingBackslash;
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);
TrailingBackslash = FALSE; if (NtPathU.Length >= sizeof(WCHAR) && NtPathU.Buffer[NtPathU.Length / sizeof(WCHAR) - 1]) { TrailingBackslash = TRUE; }
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 if (Status == STATUS_FILE_IS_A_DIRECTORY && TrailingBackslash) { SetLastError(ERROR_PATH_NOT_FOUND); } 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 WINAPIOpenFile(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 INVALID_FILE_ATTRIBUTES: /* 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)(ULONG_PTR) 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_ERROR; }
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_ERROR; }
// FILE_SHARE_READ // FILE_NO_INTERMEDIATE_BUFFERING
InitializeObjectAttributes(&ObjectAttributes, &FileNameString, OBJ_CASE_INSENSITIVE | OBJ_INHERIT, NULL, 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_ERROR; }
if (uStyle & OF_EXIST) { NtClose(FileHandle); return (HFILE)1; }
return (HFILE)(ULONG_PTR)FileHandle;}
/* * @unimplemented */BOOLWINAPIOpenDataFile(HANDLE hFile, DWORD dwUnused){ STUB; return FALSE;}
/* * @unimplemented */HANDLEWINAPIReOpenFile(IN HANDLE hOriginalFile, IN DWORD dwDesiredAccess, IN DWORD dwShareMode, IN DWORD dwFlags){ STUB; return INVALID_HANDLE_VALUE;}
/* EOF */