/* * @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; 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 */ if (0 == _wcsicmp(L"CONOUT$", lpFileName) || 0 == _wcsicmp(L"CONIN$", lpFileName)) { return OpenConsoleW(lpFileName, 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; 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 allways be waited on and querying attributes are allways 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 : 0); } else if (dwCreationDisposition == FILE_OVERWRITE_IF) { SetLastError(IoStatusBlock.Information == FILE_OVERWRITTEN ? ERROR_ALREADY_EXISTS : 0); } return FileHandle; }
BOOL BackupReadEaData(HANDLE hFile, BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif) { if (pbuc->fStreamStart) { IO_STATUS_BLOCK iosb; while (TRUE) { NTSTATUS Status; FILE_EA_INFORMATION fei; Status = NtQueryEaFile( hFile, &iosb, pbuc->pBuffer, pbuc->cbBuffer, FALSE, NULL, 0, 0, (BOOLEAN) TRUE); if (NT_SUCCESS(Status) && iosb.Information != 0) { pbuc->fBufferReady = TRUE; break; } if (!BufferOverflow(Status)) { return(TRUE); // No Eas, do next stream type } Status = NtQueryInformationFile( hFile, &iosb, &fei, sizeof(fei), FileEaInformation); if (!NT_SUCCESS(Status)) { return(TRUE); // No Eas, do next stream type } if (!GrowBuffer(pbuc, (fei.EaSize * 5) / 4)) { pbuc->fAccessError = TRUE; return(FALSE); // No memory } // else grow succeeded } pbuc->head.dwStreamId = mwStreamList[pbuc->StreamIndex]; pbuc->head.dwStreamAttributes = STREAM_NORMAL_ATTRIBUTE; pbuc->head.dwStreamNameSize = 0; pbuc->cbHeader = CB_NAMELESSHEADER; pbuc->head.Size.HighPart = 0; pbuc->head.Size.LowPart = iosb.Information; pbuc->fStreamStart = FALSE; } else if (pbuc->liStreamOffset.HighPart != 0 || pbuc->liStreamOffset.LowPart >= pbuc->cbHeader) { BackupReadBuffer(pbuc, pbif); } return(TRUE); }