// PELF_FILE_SET_SIZE_ROUTINE static NTSTATUS NTAPI LogfpSetFileSize(IN PEVTLOGFILE LogFile, IN ULONG FileSize, // SIZE_T IN ULONG OldFileSize) // SIZE_T { NTSTATUS Status; PLOGFILE pLogFile = (PLOGFILE)LogFile; IO_STATUS_BLOCK IoStatusBlock; FILE_END_OF_FILE_INFORMATION FileEofInfo; FILE_ALLOCATION_INFORMATION FileAllocInfo; UNREFERENCED_PARAMETER(OldFileSize); // FIXME: Should we round up FileSize ?? FileEofInfo.EndOfFile.QuadPart = FileSize; Status = NtSetInformationFile(pLogFile->FileHandle, &IoStatusBlock, &FileEofInfo, sizeof(FileEofInfo), FileEndOfFileInformation); if (!NT_SUCCESS(Status)) return Status; FileAllocInfo.AllocationSize.QuadPart = FileSize; Status = NtSetInformationFile(pLogFile->FileHandle, &IoStatusBlock, &FileAllocInfo, sizeof(FileAllocInfo), FileAllocationInformation); return Status; }
NTSTATUS NtDeleteFile2(POBJECT_ATTRIBUTES ObjectAttributes) { HANDLE hFile; IO_STATUS_BLOCK IoStatusBlock; auto Status = NtOpenFile(&hFile, SYNCHRONIZE | DELETE, ObjectAttributes, &IoStatusBlock, FILE_SHARE_DELETE | FILE_SHARE_READ, FILE_OPEN_REPARSE_POINT | FILE_OPEN_FOR_BACKUP_INTENT); if (Status) { return Status; } FILE_DISPOSITION_INFORMATION Dispostion = { TRUE }; Status = NtSetInformationFile(hFile, &IoStatusBlock, &Dispostion, sizeof(Dispostion), FileDispositionInformation); NtClose(hFile); if (Status == 0) return 0; //使用文件取代法删除 auto cbData = ObjectAttributes->ObjectName->Length + sizeof(L"~$") - 2; UNICODE_STRING TempFileName = { cbData,cbData, (wchar_t*)new byte[cbData] }; memcpy(TempFileName.Buffer, ObjectAttributes->ObjectName->Buffer, ObjectAttributes->ObjectName->Length); *(wchar_t*)(((byte*)TempFileName.Buffer) + ObjectAttributes->ObjectName->Length) = L'~'; *(wchar_t*)(((byte*)TempFileName.Buffer) + ObjectAttributes->ObjectName->Length + 2) = L'$'; OBJECT_ATTRIBUTES ObjectAttributes2 = { sizeof(OBJECT_ATTRIBUTES),ObjectAttributes->RootDirectory, &TempFileName, OBJ_CASE_INSENSITIVE }; auto Status2 = NtCreateFile(&hFile, SYNCHRONIZE | DELETE, &ObjectAttributes2, &IoStatusBlock, 0, FILE_ATTRIBUTE_NORMAL, 0, FILE_CREATE, FILE_OPEN_FOR_BACKUP_INTENT | FILE_DELETE_ON_CLOSE, NULL, 0); delete[](byte*)TempFileName.Buffer; cbData = sizeof(FILE_RENAME_INFORMATION) + ObjectAttributes->ObjectName->Length; FILE_RENAME_INFORMATION* pRenameInfo = (FILE_RENAME_INFORMATION*)new byte[cbData]; memcpy(pRenameInfo->FileName, ObjectAttributes->ObjectName->Buffer, ObjectAttributes->ObjectName->Length); pRenameInfo->ReplaceIfExists = TRUE; pRenameInfo->RootDirectory = ObjectAttributes->RootDirectory; pRenameInfo->FileNameLength = ObjectAttributes->ObjectName->Length; //FILE_RENAME_INFORMATION RenameInfo = {TRUE,hRootDir ,FileName.}; Status2 = NtSetInformationFile(hFile, &IoStatusBlock, pRenameInfo, cbData, FileRenameInformation); delete[](byte*)pRenameInfo; NtClose(hFile); return Status2 == 0 ? 0 : Status; }
static int winfs_link(struct mount_point *mp, struct file *f, const char *newpath) { AcquireSRWLockShared(&f->rw_lock); struct winfs_file *winfile = (struct winfs_file *) f; NTSTATUS status; int r = 0; char buf[sizeof(FILE_LINK_INFORMATION) + PATH_MAX * 2]; FILE_LINK_INFORMATION *info = (FILE_LINK_INFORMATION *)buf; info->ReplaceIfExists = FALSE; info->RootDirectory = NULL; info->FileNameLength = 2 * filename_to_nt_pathname(mp, newpath, info->FileName, PATH_MAX); if (info->FileNameLength == 0) { r = -L_ENOENT; goto out; } IO_STATUS_BLOCK status_block; status = NtSetInformationFile(winfile->handle, &status_block, info, info->FileNameLength + sizeof(FILE_LINK_INFORMATION), FileLinkInformation); if (!NT_SUCCESS(status)) { log_warning("NtSetInformationFile() failed, status: %x.", status); r = -L_ENOENT; goto out; } out: ReleaseSRWLockShared(&f->rw_lock); return r; }
VOID SetupDeleteDirectoryFile(_In_ PWSTR FileName) { HANDLE tempHandle; FILE_DISPOSITION_INFORMATION dispositionInfo; IO_STATUS_BLOCK isb; if (NT_SUCCESS(PhCreateFileWin32( &tempHandle, FileName, FILE_GENERIC_WRITE | DELETE, 0, 0, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT ))) { dispositionInfo.DeleteFile = TRUE; NtSetInformationFile( tempHandle, &isb, &dispositionInfo, sizeof(FILE_DISPOSITION_INFORMATION), FileDispositionInformation ); NtClose(tempHandle); } }
static NTSTATUS SetLastWriteTime( HANDLE FileHandle, LARGE_INTEGER LastWriteTime ) { NTSTATUS errCode = STATUS_SUCCESS; IO_STATUS_BLOCK IoStatusBlock; FILE_BASIC_INFORMATION FileBasic; errCode = NtQueryInformationFile (FileHandle, &IoStatusBlock, &FileBasic, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation); if (!NT_SUCCESS(errCode)) { WARN("Error 0x%08x obtaining FileBasicInformation\n", errCode); } else { FileBasic.LastWriteTime.QuadPart = LastWriteTime.QuadPart; errCode = NtSetInformationFile (FileHandle, &IoStatusBlock, &FileBasic, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation); if (!NT_SUCCESS(errCode)) { WARN("Error 0x%0x setting LastWriteTime\n", errCode); } } return errCode; }
NTSTATUS BowserDebugCall( IN PLMDR_REQUEST_PACKET InputBuffer, IN ULONG InputBufferLength ) { NTSTATUS Status; PAGED_CODE(); ASSERT (IoGetCurrentProcess() == BowserFspProcess); if (InputBufferLength < sizeof(LMDR_REQUEST_PACKET)) { return STATUS_BUFFER_TOO_SMALL; } if (InputBuffer->Version != LMDR_REQUEST_PACKET_VERSION) { return (Status = STATUS_INVALID_PARAMETER); } if (InputBuffer->Parameters.Debug.OpenLog && InputBuffer->Parameters.Debug.CloseLog) { return (Status = STATUS_INVALID_PARAMETER); } if (InputBuffer->Parameters.Debug.OpenLog) { Status = BowserOpenTraceLogFile(InputBuffer->Parameters.Debug.TraceFileName); return Status; } else if (InputBuffer->Parameters.Debug.CloseLog) { Status = ZwClose(BrowserTraceLogHandle); if (NT_SUCCESS(Status)) { BrowserTraceLogHandle = NULL; } return Status; } else if (InputBuffer->Parameters.Debug.TruncateLog) { FILE_END_OF_FILE_INFORMATION EndOfFileInformation; IO_STATUS_BLOCK IoStatus; if (BrowserTraceLogHandle == NULL) { return STATUS_INVALID_HANDLE; } EndOfFileInformation.EndOfFile.HighPart = 0; EndOfFileInformation.EndOfFile.LowPart = 0; Status = NtSetInformationFile(BrowserTraceLogHandle, &IoStatus, &EndOfFileInformation, sizeof(EndOfFileInformation), FileEndOfFileInformation); return Status; } else { BowserDebugTraceLevel = InputBuffer->Parameters.Debug.DebugTraceBits; KdPrint(("Setting Browser Debug Trace Bits to %lx\n", BowserDebugTraceLevel)); } return STATUS_SUCCESS; }
/** Windows/NT worker. * @todo rename to rtFileWinSetAttributes */ int rtFileNativeSetAttributes(HANDLE hFile, ULONG fAttributes) { IO_STATUS_BLOCK IoStatusBlock; memset(&IoStatusBlock, 0, sizeof(IoStatusBlock)); /* * Members that are set 0 will not be modified on the file object. * See http://msdn.microsoft.com/en-us/library/aa491634.aspx (the struct docs) * for details. */ FILE_BASIC_INFORMATION Info; memset(&Info, 0, sizeof(Info)); Info.FileAttributes = fAttributes; #if 0 /** @todo resolve dynamically to avoid dragging in NtDll? */ NTSTATUS Status = NtSetInformationFile(hFile, &IoStatusBlock, &Info, sizeof(Info), FileBasicInformation); return RtlNtStatusToDosError(Status); #endif return 1; }
int XSetFilePointer( int handle, int distanceToMove, int *newFilePointer, int moveMethod) { FILE_POSITION_INFORMATION positionInfo; LARGE_INTEGER targetPointer; IO_STATUS_BLOCK ioStatusBlock; NTSTATUS status; int filesize; #ifdef DEBUG debugPrint("XSetFilePointer handle=%08x distance=%08x method=%02x\n", handle, distanceToMove, moveMethod); #endif // Calculate the target pointer switch (moveMethod) { case FILE_BEGIN: // From the beginning of the file targetPointer.u.HighPart = 0; targetPointer.u.LowPart = distanceToMove; break; case FILE_CURRENT: // From the current position status = NtQueryInformationFile((void*)handle, &ioStatusBlock, &positionInfo, sizeof(positionInfo), FilePositionInformation); if (!NT_SUCCESS(status)) return RtlNtStatusToDosError(status); targetPointer.u.HighPart = 0; targetPointer.u.LowPart = positionInfo.CurrentByteOffset.u.LowPart + distanceToMove; break; case FILE_END: // From the end of the file status = XGetFileSize(handle, &filesize); if (!NT_SUCCESS(status)) return RtlNtStatusToDosError(status); targetPointer.u.HighPart = 0; targetPointer.u.LowPart -= distanceToMove; break; default: return ERROR_INVALID_PARAMETER; } // Don't allow a negative seek if ((targetPointer.u.LowPart & 0x80000000) != 0) return ERROR_NEGATIVE_SEEK; // Fill in the new position information positionInfo.CurrentByteOffset.u.HighPart = targetPointer.u.HighPart; positionInfo.CurrentByteOffset.u.LowPart= targetPointer.u.LowPart; // Set the new position status = NtSetInformationFile((void*)handle, &ioStatusBlock, &positionInfo, sizeof(positionInfo), FilePositionInformation); if (!NT_SUCCESS(status)) return RtlNtStatusToDosError(status); else { if (newFilePointer) *newFilePointer = targetPointer.u.LowPart; return STATUS_SUCCESS; } }
static int winfs_open(struct file_system *fs, const char *pathname, int flags, int mode, struct file **fp, char *target, int buflen) { /* TODO: mode */ DWORD desired_access, create_disposition; HANDLE handle; if (flags & O_PATH) desired_access = 0; else if (flags & O_RDWR) desired_access = GENERIC_READ | GENERIC_WRITE; else if (flags & O_WRONLY) desired_access = GENERIC_WRITE; else desired_access = GENERIC_READ; if (flags & __O_DELETE) desired_access |= DELETE; if (flags & O_EXCL) create_disposition = FILE_CREATE; else if (flags & O_CREAT) create_disposition = FILE_OPEN_IF; else create_disposition = FILE_OPEN; int r = open_file(&handle, pathname, desired_access, create_disposition, flags, fp != NULL, target, buflen); if (r < 0 || r == 1) return r; if ((flags & O_TRUNC) && ((flags & O_WRONLY) || (flags & O_RDWR))) { /* Truncate the file */ FILE_END_OF_FILE_INFORMATION info; info.EndOfFile.QuadPart = 0; IO_STATUS_BLOCK status_block; NTSTATUS status = NtSetInformationFile(handle, &status_block, &info, sizeof(info), FileEndOfFileInformation); if (!NT_SUCCESS(status)) log_error("NtSetInformationFile() failed, status: %x", status); } if (fp) { int pathlen = strlen(pathname); struct winfs_file *file = (struct winfs_file *)kmalloc(sizeof(struct winfs_file) + pathlen); file_init(&file->base_file, &winfs_ops, flags); file->handle = handle; SECURITY_ATTRIBUTES attr; attr.nLength = sizeof(SECURITY_ATTRIBUTES); attr.bInheritHandle = TRUE; attr.lpSecurityDescriptor = NULL; /* TODO: Don't need this mutex for directory or symlink */ file->fp_mutex = CreateMutexW(&attr, FALSE, NULL); file->restart_scan = 1; file->pathlen = pathlen; memcpy(file->pathname, pathname, pathlen); *fp = (struct file *)file; } else CloseHandle(handle); return 0; }
static int winfs_unlink(struct mount_point *mp, const char *pathname) { WCHAR wpathname[PATH_MAX]; int len = filename_to_nt_pathname(mp, pathname, wpathname, PATH_MAX); if (len <= 0) return -L_ENOENT; UNICODE_STRING object_name; RtlInitCountedUnicodeString(&object_name, wpathname, len * sizeof(WCHAR)); OBJECT_ATTRIBUTES attr; attr.Length = sizeof(OBJECT_ATTRIBUTES); attr.RootDirectory = NULL; attr.ObjectName = &object_name; attr.Attributes = 0; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL; IO_STATUS_BLOCK status_block; NTSTATUS status; HANDLE handle; status = NtOpenFile(&handle, DELETE, &attr, &status_block, FILE_SHARE_DELETE, FILE_NON_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT); if (!NT_SUCCESS(status)) { if (status != STATUS_SHARING_VIOLATION) { log_warning("NtOpenFile() failed, status: %x", status); return -L_ENOENT; } /* This file has open handles in some processes, even we set delete disposition flags * The actual deletion of the file will be delayed to the last handle closing * To make the file disappear from its parent directory immediately, we move the file * to Windows recycle bin prior to deletion. */ status = NtOpenFile(&handle, DELETE, &attr, &status_block, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_NON_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT); if (!NT_SUCCESS(status)) { log_warning("NtOpenFile() failed, status: %x", status); return -L_EBUSY; } status = move_to_recycle_bin(handle, wpathname); if (!NT_SUCCESS(status)) return -L_EBUSY; } /* Set disposition flag */ FILE_DISPOSITION_INFORMATION info; info.DeleteFile = TRUE; status = NtSetInformationFile(handle, &status_block, &info, sizeof(info), FileDispositionInformation); if (!NT_SUCCESS(status)) { log_warning("NtSetInformation(FileDispositionInformation) failed, status: %x", status); return -L_EBUSY; } NtClose(handle); return 0; }
int XDeleteDirectory(char *directoryName) { ANSI_STRING xboxFilename; IO_STATUS_BLOCK ioStatusBlock; OBJECT_ATTRIBUTES objectAttributes; FILE_DISPOSITION_INFORMATION deleteInfo; NTSTATUS status; int handle; #ifdef DEBUG debugPrint("XDeleteDirectory directoryName=%s\n", directoryName); #endif char tmp[200]; int rc = XConvertDOSFilenameToXBOX(directoryName, tmp); if (rc != STATUS_SUCCESS) return rc; RtlInitAnsiString(&xboxFilename, tmp); objectAttributes.RootDirectory = NULL; objectAttributes.Attributes = OBJ_CASE_INSENSITIVE; objectAttributes.ObjectName = &xboxFilename; // Open the file for deletion status = NtCreateFile( (PHANDLE)&handle, DELETE | SYNCHRONIZE, &objectAttributes, &ioStatusBlock, NULL, 0, FILE_SHARE_DELETE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE); if (!NT_SUCCESS(status)) return RtlNtStatusToDosError(status); // Delete the file deleteInfo.DeleteFile = TRUE; status = NtSetInformationFile( (HANDLE)handle, &ioStatusBlock, &deleteInfo, sizeof(deleteInfo), FileDispositionInformation); if (!NT_SUCCESS(status)) return RtlNtStatusToDosError(status); else { // Close the dead handle and return NtClose((HANDLE)handle); return STATUS_SUCCESS; } }
BOOL APIENTRY SetMailslotInfo( IN HANDLE hMailslot, IN DWORD lReadTimeout ) /*++ Routine Description: This function will set the read timeout for the specified mailslot. Arguments: hMailslot - A handle to the mailslot. lReadTimeout - The new read timeout, in milliseconds. Return Value: TRUE - The operation was successful. FALSE/NULL - The operation failed. Extended error status is available using GetLastError. --*/ { NTSTATUS status; IO_STATUS_BLOCK ioStatusBlock; FILE_MAILSLOT_SET_INFORMATION mailslotInfo; LARGE_INTEGER timeout; if ( lReadTimeout == MAILSLOT_WAIT_FOREVER ) { timeout.HighPart = 0x7FFFFFFF; timeout.LowPart = 0xFFFFFFFF; } else { timeout.QuadPart = - (LONGLONG)UInt32x32To64( lReadTimeout, 10 * 1000 ); } mailslotInfo.ReadTimeout = &timeout; status = NtSetInformationFile( hMailslot, &ioStatusBlock, &mailslotInfo, sizeof( mailslotInfo ), FileMailslotSetInformation ); if ( !NT_SUCCESS( status ) ) { BaseSetLastNTError( status ); return ( FALSE ); } return TRUE; }
/* * @implemented */ VOID WINAPI BaseMarkFileForDelete(IN HANDLE FileHandle, IN ULONG FileAttributes) { IO_STATUS_BLOCK IoStatusBlock; FILE_BASIC_INFORMATION FileBasicInfo; FILE_DISPOSITION_INFORMATION FileDispositionInfo; /* If no attributes were given, get them */ if (!FileAttributes) { FileBasicInfo.FileAttributes = 0; NtQueryInformationFile(FileHandle, &IoStatusBlock, &FileBasicInfo, sizeof(FileBasicInfo), FileBasicInformation); FileAttributes = FileBasicInfo.FileAttributes; } /* If file is marked as RO, reset its attributes */ if (FileAttributes & FILE_ATTRIBUTE_READONLY) { RtlZeroMemory(&FileBasicInfo, sizeof(FileBasicInfo)); FileBasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL; NtSetInformationFile(FileHandle, &IoStatusBlock, &FileBasicInfo, sizeof(FileBasicInfo), FileBasicInformation); } /* Finally, mark the file for deletion */ FileDispositionInfo.DeleteFile = TRUE; NtSetInformationFile(FileHandle, &IoStatusBlock, &FileDispositionInfo, sizeof(FileDispositionInfo), FileDispositionInformation); }
NTSTATUS NTAPI SmpDeletePagingFile(IN PUNICODE_STRING FileName) { NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; HANDLE FileHandle; FILE_DISPOSITION_INFORMATION Disposition; /* Open the page file */ InitializeObjectAttributes(&ObjectAttributes, FileName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenFile(&FileHandle, DELETE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_NON_DIRECTORY_FILE); if (NT_SUCCESS(Status)) { /* Delete it */ Disposition.DeleteFile = TRUE; Status = NtSetInformationFile(FileHandle, &IoStatusBlock, &Disposition, sizeof(Disposition), FileDispositionInformation); if (!NT_SUCCESS(Status)) { DPRINT1("SMSS:PFILE: Failed to delete page file `%wZ' (status %X)\n", FileName, Status); } else { DPRINT1("SMSS:PFILE: Deleted stale paging file - %wZ\n", FileName); } /* Close the handle */ NtClose(FileHandle); } else { DPRINT1("SMSS:PFILE: Failed to open for deletion page file `%wZ' (status %X)\n", FileName, Status); } /* All done */ return Status; }
static int winfs_open(struct file_system *fs, const char *pathname, int flags, int mode, struct file **fp, char *target, int buflen) { /* TODO: mode */ DWORD desired_access, create_disposition; HANDLE handle; if (flags & O_PATH) desired_access = 0; else if (flags & O_RDWR) desired_access = GENERIC_READ | GENERIC_WRITE; else if (flags & O_WRONLY) desired_access = GENERIC_WRITE; else desired_access = GENERIC_READ; if (flags & __O_DELETE) desired_access |= DELETE; if (flags & O_EXCL) create_disposition = FILE_CREATE; else if (flags & O_CREAT) create_disposition = FILE_OPEN_IF; else create_disposition = FILE_OPEN; int r = open_file(&handle, pathname, desired_access, create_disposition, flags, fp != NULL, target, buflen); if (r < 0 || r == 1) return r; if ((flags & O_TRUNC) && ((flags & O_WRONLY) || (flags & O_RDWR))) { /* Truncate the file */ FILE_END_OF_FILE_INFORMATION info; info.EndOfFile.QuadPart = 0; IO_STATUS_BLOCK status_block; NTSTATUS status = NtSetInformationFile(handle, &status_block, &info, sizeof(info), FileEndOfFileInformation); if (!NT_SUCCESS(status)) log_error("NtSetInformationFile() failed, status: %x\n", status); } if (fp) { int pathlen = strlen(pathname); struct winfs_file *file = (struct winfs_file *)kmalloc(sizeof(struct winfs_file) + pathlen); file->base_file.op_vtable = &winfs_ops; file->base_file.ref = 1; file->base_file.flags = flags; file->handle = handle; file->restart_scan = 1; file->pathlen = pathlen; memcpy(file->pathname, pathname, pathlen); *fp = (struct file *)file; } else CloseHandle(handle); return 0; }
/*++ * @name SmpDeleteFile * * The SmpDeleteFile function deletes a specify file. * * @param lpFileName * the name of a file which should be deleted * * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL * othwerwise. * * @remarks * This function is called by SmpMoveFilesQueryRoutine(). * * *--*/ NTSTATUS SmpDeleteFile( IN LPCWSTR lpFileName ) { FILE_DISPOSITION_INFORMATION FileDispInfo; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; UNICODE_STRING FileNameU; HANDLE FileHandle; NTSTATUS Status; DPRINT("SmpDeleteFile ( %S )\n", lpFileName); if( !lpFileName ) return (STATUS_INVALID_PARAMETER); RtlInitUnicodeString(&FileNameU, lpFileName); InitializeObjectAttributes(&ObjectAttributes, &FileNameU, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtCreateFile (&FileHandle, DELETE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if( !NT_SUCCESS(Status) ) { DPRINT("NtCreateFile() failed (Status %lx)\n", Status); return (Status); } FileDispInfo.DeleteFile = TRUE; Status = NtSetInformationFile( FileHandle, &IoStatusBlock, &FileDispInfo, sizeof(FILE_DISPOSITION_INFORMATION), FileDispositionInformation ); NtClose(FileHandle); return (Status); }
/* * @implemented */ BOOL WINAPI SetFileShortNameW( HANDLE hFile, LPCWSTR lpShortName) { NTSTATUS Status; ULONG NeededSize; UNICODE_STRING ShortName; IO_STATUS_BLOCK IoStatusBlock; PFILE_NAME_INFORMATION FileNameInfo; if(IsConsoleHandle(hFile)) { SetLastError(ERROR_INVALID_HANDLE); return FALSE; } if(!lpShortName) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } RtlInitUnicodeString(&ShortName, lpShortName); NeededSize = sizeof(FILE_NAME_INFORMATION) + ShortName.Length + sizeof(WCHAR); if(!(FileNameInfo = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, NeededSize))) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } FileNameInfo->FileNameLength = ShortName.Length; RtlCopyMemory(FileNameInfo->FileName, ShortName.Buffer, ShortName.Length); Status = NtSetInformationFile(hFile, &IoStatusBlock, //out FileNameInfo, NeededSize, FileShortNameInformation); RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameInfo); if(!NT_SUCCESS(Status)) { BaseSetLastNTError(Status); return FALSE; } return TRUE; }
/* * FUNCTION: Sets attributes on a file * ARGUMENTS: * File = Pointer to CFFILE node for file * RETURNS: * Status of operation */ static BOOL SetAttributesOnFile(PCFFILE File, HANDLE hFile) { FILE_BASIC_INFORMATION FileBasic; IO_STATUS_BLOCK IoStatusBlock; NTSTATUS NtStatus; ULONG Attributes = 0; if (File->Attributes & CAB_ATTRIB_READONLY) Attributes |= FILE_ATTRIBUTE_READONLY; if (File->Attributes & CAB_ATTRIB_HIDDEN) Attributes |= FILE_ATTRIBUTE_HIDDEN; if (File->Attributes & CAB_ATTRIB_SYSTEM) Attributes |= FILE_ATTRIBUTE_SYSTEM; if (File->Attributes & CAB_ATTRIB_DIRECTORY) Attributes |= FILE_ATTRIBUTE_DIRECTORY; if (File->Attributes & CAB_ATTRIB_ARCHIVE) Attributes |= FILE_ATTRIBUTE_ARCHIVE; NtStatus = NtQueryInformationFile(hFile, &IoStatusBlock, &FileBasic, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation); if (!NT_SUCCESS(NtStatus)) { DPRINT("NtQueryInformationFile() failed (%x)\n", NtStatus); } else { FileBasic.FileAttributes = Attributes; NtStatus = NtSetInformationFile(hFile, &IoStatusBlock, &FileBasic, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation); if (!NT_SUCCESS(NtStatus)) { DPRINT("NtSetInformationFile() failed (%x)\n", NtStatus); } } return NT_SUCCESS(NtStatus); }
static int winfs_truncate(struct file *f, loff_t length) { struct winfs_file *winfile = (struct winfs_file *) f; /* TODO: Correct errno */ FILE_END_OF_FILE_INFORMATION info; info.EndOfFile.QuadPart = length; IO_STATUS_BLOCK status_block; NTSTATUS status; status = NtSetInformationFile(winfile->handle, &status_block, &info, sizeof(info), FileEndOfFileInformation); if (!NT_SUCCESS(status)) { log_warning("NtSetInformationFile(FileEndOfFileInformation) failed, status: %x\n", status); return -EIO; } return 0; }
static int winfs_rename(struct mount_point *mp, struct file *f, const char *newpath) { AcquireSRWLockShared(&f->rw_lock); struct winfs_file *winfile = (struct winfs_file *)f; char buf[sizeof(FILE_RENAME_INFORMATION) + PATH_MAX * 2]; NTSTATUS status; int r = 0; int retry_count = 5; retry: if (--retry_count == 0) { r = -L_EPERM; goto out; } FILE_RENAME_INFORMATION *info = (FILE_RENAME_INFORMATION *)buf; info->ReplaceIfExists = TRUE; info->RootDirectory = NULL; info->FileNameLength = 2 * filename_to_nt_pathname(mp, newpath, info->FileName, PATH_MAX); if (info->FileNameLength == 0) { r = -L_ENOENT; goto out; } IO_STATUS_BLOCK status_block; status = NtSetInformationFile(winfile->handle, &status_block, info, info->FileNameLength + sizeof(FILE_RENAME_INFORMATION), FileRenameInformation); if (!NT_SUCCESS(status)) { if (status == STATUS_ACCESS_DENIED) { /* The destination exists and the operation cannot be completed via a native operation. * We remove the destination file first, then move this file again. */ r = winfs_unlink(mp, newpath); if (r) goto out; goto retry; } log_warning("NtSetInformationFile() failed, status: %x", status); r = -L_ENOENT; goto out; } out: ReleaseSRWLockShared(&f->rw_lock); return r; }
NTSTATUS NtSetFileAttributes(POBJECT_ATTRIBUTES ObjectAttributes, DWORD FileAttributes) { HANDLE hFile; //OBJECT_ATTRIBUTES ObjectAttributes = { sizeof(OBJECT_ATTRIBUTES), NULL, (UNICODE_STRING*)&FileName, OBJ_CASE_INSENSITIVE }; IO_STATUS_BLOCK IoStatusBlock; auto Status = NtOpenFile(&hFile, FILE_WRITE_ATTRIBUTES | SYNCHRONIZE, ObjectAttributes, &IoStatusBlock, FILE_SHARE_VALID_FLAGS, FILE_OPEN_REPARSE_POINT | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT); if (Status) { return Status; } FILE_BASIC_INFORMATION Info = { {},{},{},{}, FileAttributes }; Status = NtSetInformationFile(hFile, &IoStatusBlock, &Info, sizeof(Info), FileBasicInformation); NtClose(hFile); return Status; }
static int winfs_rename(struct file *f, const char *newpath) { struct winfs_file *winfile = (struct winfs_file *)f; char buf[sizeof(FILE_RENAME_INFORMATION) + PATH_MAX * 2]; NTSTATUS status; FILE_RENAME_INFORMATION *info = (FILE_RENAME_INFORMATION *)buf; info->ReplaceIfExists = TRUE; /* TODO: This should be worked on to provide true Linux semantics (refer to unlink()) */ info->RootDirectory = NULL; info->FileNameLength = 2 * filename_to_nt_pathname(newpath, info->FileName, PATH_MAX); if (info->FileNameLength == 0) return -ENOENT; IO_STATUS_BLOCK status_block; status = NtSetInformationFile(winfile->handle, &status_block, info, info->FileNameLength + sizeof(FILE_RENAME_INFORMATION), FileRenameInformation); if (!NT_SUCCESS(status)) { log_warning("NtSetInformationFile() failed, status: %x\n", status); return -ENOENT; } return 0; }
static int winfs_link(struct file *f, const char *newpath) { struct winfs_file *winfile = (struct winfs_file *) f; NTSTATUS status; char buf[sizeof(FILE_LINK_INFORMATION) + PATH_MAX * 2]; FILE_LINK_INFORMATION *info = (FILE_LINK_INFORMATION *)buf; info->ReplaceIfExists = FALSE; info->RootDirectory = NULL; info->FileNameLength = 2 * filename_to_nt_pathname(newpath, info->FileName, PATH_MAX); if (info->FileNameLength == 0) return -ENOENT; IO_STATUS_BLOCK status_block; status = NtSetInformationFile(winfile->handle, &status_block, info, info->FileNameLength + sizeof(FILE_LINK_INFORMATION), FileLinkInformation); if (!NT_SUCCESS(status)) { log_warning("NtSetInformationFile() failed, status: %x.\n", status); return -ENOENT; } return 0; }
/* * @implemented */ BOOL WINAPI SetMailslotInfo(IN HANDLE hMailslot, IN DWORD lReadTimeout) { FILE_MAILSLOT_SET_INFORMATION Buffer; LARGE_INTEGER Timeout; IO_STATUS_BLOCK Iosb; NTSTATUS Status; if (lReadTimeout == MAILSLOT_WAIT_FOREVER) { /* Set the max */ Timeout.QuadPart = 0xFFFFFFFFFFFFFFFFLL; } else { /* Convert to NT format */ Timeout.QuadPart = lReadTimeout * -10000LL; } Buffer.ReadTimeout = &Timeout; Status = NtSetInformationFile(hMailslot, &Iosb, &Buffer, sizeof(FILE_MAILSLOT_SET_INFORMATION), FileMailslotSetInformation); if (!NT_SUCCESS(Status)) { DPRINT1("NtSetInformationFile failed (Status %x)!\n", Status); BaseSetLastNTError(Status); return FALSE; } return TRUE; }
int XRenameFile( char *oldFilename, char *newFilename) { ANSI_STRING xboxFilename; IO_STATUS_BLOCK ioStatusBlock; OBJECT_ATTRIBUTES objectAttributes; FILE_RENAME_INFORMATION renameInfo; NTSTATUS status; int handle; #ifdef DEBUG debugPrint("XRenameFile oldFilename=%s newFilename=%s\n", oldFilename, newFilename); #endif char tmp[200]; int rc = XConvertDOSFilenameToXBOX(oldFilename, tmp); if (rc != STATUS_SUCCESS) return rc; RtlInitAnsiString(&xboxFilename, tmp); objectAttributes.RootDirectory = NULL; objectAttributes.Attributes = OBJ_CASE_INSENSITIVE; objectAttributes.ObjectName = &xboxFilename; // Try to open the file // I'm not sure why we have to use these particular flags, but we do. status = NtCreateFile( (PHANDLE)handle, DELETE | SYNCHRONIZE, &objectAttributes, &ioStatusBlock, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_NON_DIRECTORY_FILE); if (!NT_SUCCESS(status)) return RtlNtStatusToDosError(status); // Set up the rename information rc = XConvertDOSFilenameToXBOX(newFilename, tmp); if (rc != STATUS_SUCCESS) return rc; RtlInitAnsiString(&renameInfo.FileName, tmp); renameInfo.ReplaceIfExists = TRUE; renameInfo.RootDirectory = NULL; // Try to rename the file status = NtSetInformationFile( (HANDLE)handle, &ioStatusBlock, &renameInfo, sizeof(renameInfo), FileRenameInformation); if (!NT_SUCCESS(status)) { NtClose((HANDLE)handle); return RtlNtStatusToDosError(status); } else { NtClose((HANDLE)handle); return STATUS_SUCCESS; } }
VOID Delete( IN PCHAR FileName ) { NTSTATUS Status; HANDLE FileHandle; OBJECT_ATTRIBUTES ObjectAttributes; STRING NameString; IO_STATUS_BLOCK IoStatus; // // Get the filename // simprintf("Delete ", 0); simprintf(FileName, 0); simprintf("\n", 0); // // Open the file for delete access // RtlInitString( &NameString, FileName ); InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL ); if (!NT_SUCCESS(Status = NtCreateFile( &FileHandle, DELETE | SYNCHRONIZE, &ObjectAttributes, &IoStatus, (PLARGE_INTEGER)NULL, 0L, 0L, FILE_OPEN, WriteThrough, (PVOID)NULL, 0L ))) { CreateFileError( Status, FileName ); return; } // // Mark the file for delete // ((PFILE_DISPOSITION_INFORMATION)&Buffer[0])->DeleteFile = TRUE; if (!NT_SUCCESS(Status = NtSetInformationFile( FileHandle, &IoStatus, Buffer, sizeof(FILE_DISPOSITION_INFORMATION), FileDispositionInformation))) { SetInformationFileError( Status ); return; } // // Now close the file // if (!NT_SUCCESS(Status = NtClose( FileHandle ))) { CloseError( Status ); } // // And return to our caller // return; }
NTSTATUS SetupCopyFile( PWCHAR SourceFileName, PWCHAR DestinationFileName) { OBJECT_ATTRIBUTES ObjectAttributes; HANDLE FileHandleSource; HANDLE FileHandleDest; static IO_STATUS_BLOCK IoStatusBlock; FILE_STANDARD_INFORMATION FileStandard; FILE_BASIC_INFORMATION FileBasic; ULONG RegionSize; UNICODE_STRING FileName; NTSTATUS Status; PVOID SourceFileMap = 0; HANDLE SourceFileSection; SIZE_T SourceSectionSize = 0; LARGE_INTEGER ByteOffset; #ifdef __REACTOS__ RtlInitUnicodeString(&FileName, SourceFileName); InitializeObjectAttributes(&ObjectAttributes, &FileName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenFile(&FileHandleSource, GENERIC_READ, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ, FILE_SEQUENTIAL_ONLY); if (!NT_SUCCESS(Status)) { DPRINT1("NtOpenFile failed: %x, %wZ\n", Status, &FileName); goto done; } #else FileHandleSource = CreateFileW(SourceFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (FileHandleSource == INVALID_HANDLE_VALUE) { Status = STATUS_UNSUCCESSFUL; goto done; } #endif Status = NtQueryInformationFile(FileHandleSource, &IoStatusBlock, &FileStandard, sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation); if (!NT_SUCCESS(Status)) { DPRINT1("NtQueryInformationFile failed: %x\n", Status); goto closesrc; } Status = NtQueryInformationFile(FileHandleSource, &IoStatusBlock,&FileBasic, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation); if (!NT_SUCCESS(Status)) { DPRINT1("NtQueryInformationFile failed: %x\n", Status); goto closesrc; } Status = NtCreateSection(&SourceFileSection, SECTION_MAP_READ, NULL, NULL, PAGE_READONLY, SEC_COMMIT, FileHandleSource); if (!NT_SUCCESS(Status)) { DPRINT1("NtCreateSection failed: %x, %S\n", Status, SourceFileName); goto closesrc; } Status = NtMapViewOfSection(SourceFileSection, NtCurrentProcess(), &SourceFileMap, 0, 0, NULL, &SourceSectionSize, ViewUnmap, 0, PAGE_READONLY ); if (!NT_SUCCESS(Status)) { DPRINT1("NtMapViewOfSection failed: %x, %S\n", Status, SourceFileName); goto closesrcsec; } RtlInitUnicodeString(&FileName, DestinationFileName); InitializeObjectAttributes(&ObjectAttributes, &FileName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtCreateFile(&FileHandleDest, GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, FILE_NO_INTERMEDIATE_BUFFERING | FILE_SEQUENTIAL_ONLY | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if (!NT_SUCCESS(Status)) { DPRINT1("NtCreateFile failed: %x\n", Status); goto unmapsrcsec; } RegionSize = (ULONG)PAGE_ROUND_UP(FileStandard.EndOfFile.u.LowPart); IoStatusBlock.Status = 0; ByteOffset.QuadPart = 0; Status = NtWriteFile(FileHandleDest, NULL, NULL, NULL, &IoStatusBlock, SourceFileMap, RegionSize, &ByteOffset, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("NtWriteFile failed: %x:%x, iosb: %p src: %p, size: %x\n", Status, IoStatusBlock.Status, &IoStatusBlock, SourceFileMap, RegionSize); goto closedest; } /* Copy file date/time from source file */ Status = NtSetInformationFile(FileHandleDest, &IoStatusBlock, &FileBasic, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation); if (!NT_SUCCESS(Status)) { DPRINT1("NtSetInformationFile failed: %x\n", Status); goto closedest; } /* shorten the file back to it's real size after completing the write */ Status = NtSetInformationFile(FileHandleDest, &IoStatusBlock, &FileStandard.EndOfFile, sizeof(FILE_END_OF_FILE_INFORMATION), FileEndOfFileInformation); if (!NT_SUCCESS(Status)) { DPRINT1("NtSetInformationFile failed: %x\n", Status); } closedest: NtClose(FileHandleDest); unmapsrcsec: NtUnmapViewOfSection(NtCurrentProcess(), SourceFileMap); closesrcsec: NtClose(SourceFileSection); closesrc: NtClose(FileHandleSource); done: return Status; }
BOOL APIENTRY MoveFileExW( LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, DWORD dwFlags ) /*++ Routine Description: An existing file can be renamed using MoveFile. Arguments: lpExistingFileName - Supplies the name of an existing file that is to be renamed. lpNewFileName - Supplies the new name for the existing file. The new name must reside in the same file system/drive as the existing file and must not already exist. dwFlags - Supplies optional flag bits to control the behavior of the rename. The following bits are currently defined: MOVEFILE_REPLACE_EXISTING - if the new file name exists, replace it by renaming the old file name on top of the new file name. MOVEFILE_COPY_ALLOWED - if the new file name is on a different volume than the old file name, and causes the rename operation to fail, then setting this flag allows the MoveFileEx API call to simulate the rename with a call to CopyFile followed by a call to DeleteFile to the delete the old file if the CopyFile was successful. MOVEFILE_DELAY_UNTIL_REBOOT - dont actually do the rename now, but instead queue the rename so that it will happen the next time the system boots. If this flag is set, then the lpNewFileName parameter may be NULL, in which case a delay DeleteFile of the old file name will occur the next time the system is booted. The delay rename/delete operations occur immediately after AUTOCHK is run, but prior to creating any paging files, so it can be used to delete paging files from previous boots before they are reused. MOVEFILE_WRITE_THROUGH - perform the rename operation in such a way that the file has actually been moved on the disk before the API returns to the caller. Note that this flag causes a flush at the end of a copy operation (if one were allowed and necessary), and has no effect if the rename operation is delayed until the next reboot. Return Value: TRUE - The operation was successful. FALSE/NULL - The operation failed. Extended error status is available using GetLastError. --*/ { NTSTATUS Status; BOOLEAN ReplaceIfExists; OBJECT_ATTRIBUTES Obja; HANDLE Handle; UNICODE_STRING OldFileName; UNICODE_STRING NewFileName; IO_STATUS_BLOCK IoStatusBlock; PFILE_RENAME_INFORMATION NewName; BOOLEAN TranslationStatus; RTL_RELATIVE_NAME RelativeName; PVOID FreeBuffer; ULONG OpenFlags; BOOLEAN fDoCrossVolumeMove; BOOLEAN b; #ifdef _CAIRO_ OBJECTID oid; OBJECTID *poid; // only can be valid when fDoCrossVolumeMove = TRUE #else PVOID poid = NULL; #endif // // if the target is a device, do not allow the rename ! // if ( lpNewFileName ) { if ( RtlIsDosDeviceName_U((PWSTR)lpNewFileName) ) { SetLastError(ERROR_ALREADY_EXISTS); return FALSE; } } if (dwFlags & MOVEFILE_REPLACE_EXISTING) { ReplaceIfExists = TRUE; } else { ReplaceIfExists = FALSE; } TranslationStatus = RtlDosPathNameToNtPathName_U( lpExistingFileName, &OldFileName, NULL, &RelativeName ); if ( !TranslationStatus ) { SetLastError(ERROR_PATH_NOT_FOUND); return FALSE; } FreeBuffer = OldFileName.Buffer; if (!(dwFlags & MOVEFILE_DELAY_UNTIL_REBOOT)) { if ( RelativeName.RelativeName.Length ) { OldFileName = *(PUNICODE_STRING)&RelativeName.RelativeName; } else { RelativeName.ContainingDirectory = NULL; } InitializeObjectAttributes( &Obja, &OldFileName, OBJ_CASE_INSENSITIVE, RelativeName.ContainingDirectory, NULL ); // // Open the file for delete access // OpenFlags = FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | (dwFlags & MOVEFILE_WRITE_THROUGH) ? FILE_WRITE_THROUGH : 0; Status = NtOpenFile( &Handle, #ifdef _CAIRO_ FILE_READ_ATTRIBUTES | #endif (ACCESS_MASK)DELETE | SYNCHRONIZE, &Obja, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, OpenFlags ); if ( !NT_SUCCESS(Status) ) { RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer); BaseSetLastNTError(Status); return FALSE; } } if (!(dwFlags & MOVEFILE_DELAY_UNTIL_REBOOT) || (lpNewFileName != NULL)) { TranslationStatus = RtlDosPathNameToNtPathName_U( lpNewFileName, &NewFileName, NULL, NULL ); if ( !TranslationStatus ) { RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer); SetLastError(ERROR_PATH_NOT_FOUND); NtClose(Handle); return FALSE; } } else { RtlInitUnicodeString( &NewFileName, NULL ); } if (dwFlags & MOVEFILE_DELAY_UNTIL_REBOOT) { // // copy allowed is not permitted on delayed renames // // // (typical stevewo hack, preserved for sentimental value) // // If ReplaceIfExists is TRUE, prepend an exclamation point // to the new filename in order to pass this bit of data // along to the session manager. // if (ReplaceIfExists && (NewFileName.Length != 0)) { PWSTR NewBuffer; NewBuffer = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( TMP_TAG ), NewFileName.Length + sizeof(WCHAR) ); if (NewBuffer != NULL) { NewBuffer[0] = L'!'; CopyMemory(&NewBuffer[1], NewFileName.Buffer, NewFileName.Length); NewFileName.Length += sizeof(WCHAR); NewFileName.MaximumLength += sizeof(WCHAR); RtlFreeHeap(RtlProcessHeap(), 0, NewFileName.Buffer); NewFileName.Buffer = NewBuffer; } } if ( dwFlags & MOVEFILE_COPY_ALLOWED ) { Status = STATUS_INVALID_PARAMETER; } else { Status = BasepMoveFileDelayed(&OldFileName, &NewFileName); } RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer); RtlFreeHeap(RtlProcessHeap(), 0, NewFileName.Buffer); if (NT_SUCCESS(Status)) { return(TRUE); } else { BaseSetLastNTError(Status); return(FALSE); } } RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer); FreeBuffer = NewFileName.Buffer; NewName = RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( TMP_TAG ), NewFileName.Length+sizeof(*NewName)); if (NewName != NULL) { RtlMoveMemory( NewName->FileName, NewFileName.Buffer, NewFileName.Length ); NewName->ReplaceIfExists = ReplaceIfExists; NewName->RootDirectory = NULL; NewName->FileNameLength = NewFileName.Length; RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer); Status = NtSetInformationFile( Handle, &IoStatusBlock, NewName, NewFileName.Length+sizeof(*NewName), FileRenameInformation ); RtlFreeHeap(RtlProcessHeap(), 0, NewName); } else { Status = STATUS_NO_MEMORY; } fDoCrossVolumeMove = (Status == STATUS_NOT_SAME_DEVICE) && (dwFlags & MOVEFILE_COPY_ALLOWED); #ifdef _CAIRO_ if (fDoCrossVolumeMove) { // Get the object'd OBJECTID poid = RtlQueryObjectId(Handle, &oid) == STATUS_SUCCESS ? &oid : NULL; } #endif NtClose(Handle); if ( NT_SUCCESS(Status) ) { return TRUE; } else if ( fDoCrossVolumeMove ) { HELPER_CONTEXT Context; Context.pObjectId = poid; Context.dwFlags = dwFlags; b = CopyFileExW( lpExistingFileName, lpNewFileName, poid || dwFlags & MOVEFILE_WRITE_THROUGH ? BasepCrossVolumeMoveHelper : NULL, &Context, NULL, ReplaceIfExists ? 0 : COPY_FILE_FAIL_IF_EXISTS ); if ( b ) { // // the copy worked... Delete the source of the rename // if it fails, try a set attributes and then a delete // if (!DeleteFileW( lpExistingFileName ) ) { // // If the delete fails, we will return true, but possibly // leave the source dangling // SetFileAttributesW(lpExistingFileName,FILE_ATTRIBUTE_NORMAL); DeleteFileW( lpExistingFileName ); } return TRUE; } else { return FALSE; } } else { BaseSetLastNTError(Status); return FALSE; } }
BOOL APIENTRY SetFileAttributesW( LPCWSTR lpFileName, DWORD dwFileAttributes ) /*++ Routine Description: The attributes of a file can be set using SetFileAttributes. This API provides the same functionality as DOS (int 21h, function 43H with AL=1), and provides a subset of OS/2's DosSetFileInfo. Arguments: lpFileName - Supplies the file name of the file whose attributes are to be set. dwFileAttributes - Specifies the file attributes to be set for the file. Any combination of flags is acceptable except that all other flags override the normal file attribute, FILE_ATTRIBUTE_NORMAL. FileAttributes Flags: FILE_ATTRIBUTE_NORMAL - A normal file should be created. FILE_ATTRIBUTE_READONLY - A read-only file should be created. FILE_ATTRIBUTE_HIDDEN - A hidden file should be created. FILE_ATTRIBUTE_SYSTEM - A system file should be created. FILE_ATTRIBUTE_ARCHIVE - The file should be marked so that it will be archived. Return Value: TRUE - The operation was successful. FALSE/NULL - The operation failed. Extended error status is available using GetLastError. --*/ { NTSTATUS Status; OBJECT_ATTRIBUTES Obja; HANDLE Handle; UNICODE_STRING FileName; IO_STATUS_BLOCK IoStatusBlock; FILE_BASIC_INFORMATION BasicInfo; BOOLEAN TranslationStatus; RTL_RELATIVE_NAME RelativeName; PVOID FreeBuffer; TranslationStatus = RtlDosPathNameToNtPathName_U( lpFileName, &FileName, NULL, &RelativeName ); if ( !TranslationStatus ) { SetLastError(ERROR_PATH_NOT_FOUND); return FALSE; } FreeBuffer = FileName.Buffer; if ( RelativeName.RelativeName.Length ) { FileName = *(PUNICODE_STRING)&RelativeName.RelativeName; } else { RelativeName.ContainingDirectory = NULL; } InitializeObjectAttributes( &Obja, &FileName, OBJ_CASE_INSENSITIVE, RelativeName.ContainingDirectory, NULL ); // // Open the file // Status = NtOpenFile( &Handle, (ACCESS_MASK)FILE_WRITE_ATTRIBUTES | SYNCHRONIZE, &Obja, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT ); RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer); if ( !NT_SUCCESS(Status) ) { BaseSetLastNTError(Status); return FALSE; } // // Set the attributes // RtlZeroMemory(&BasicInfo,sizeof(BasicInfo)); BasicInfo.FileAttributes = (dwFileAttributes & FILE_ATTRIBUTE_VALID_SET_FLAGS) | FILE_ATTRIBUTE_NORMAL; Status = NtSetInformationFile( Handle, &IoStatusBlock, &BasicInfo, sizeof(BasicInfo), FileBasicInformation ); NtClose(Handle); if ( NT_SUCCESS(Status) ) { return TRUE; } else { BaseSetLastNTError(Status); return FALSE; } }
BOOL APIENTRY DeleteFileW( LPCWSTR lpFileName ) /*++ Routine Description: An existing file can be deleted using DeleteFile. This API provides the same functionality as DOS (int 21h, function 41H) and OS/2's DosDelete. Arguments: lpFileName - Supplies the file name of the file to be deleted. Return Value: TRUE - The operation was successful. FALSE/NULL - The operation failed. Extended error status is available using GetLastError. --*/ { NTSTATUS Status; OBJECT_ATTRIBUTES Obja; HANDLE Handle; UNICODE_STRING FileName; IO_STATUS_BLOCK IoStatusBlock; FILE_DISPOSITION_INFORMATION Disposition; BOOLEAN TranslationStatus; RTL_RELATIVE_NAME RelativeName; PVOID FreeBuffer; TranslationStatus = RtlDosPathNameToNtPathName_U( lpFileName, &FileName, NULL, &RelativeName ); if ( !TranslationStatus ) { SetLastError(ERROR_PATH_NOT_FOUND); return FALSE; } FreeBuffer = FileName.Buffer; if ( RelativeName.RelativeName.Length ) { FileName = *(PUNICODE_STRING)&RelativeName.RelativeName; } else { RelativeName.ContainingDirectory = NULL; } InitializeObjectAttributes( &Obja, &FileName, OBJ_CASE_INSENSITIVE, RelativeName.ContainingDirectory, NULL ); // // Open the file for delete access // Status = NtOpenFile( &Handle, (ACCESS_MASK)DELETE, &Obja, &IoStatusBlock, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_NON_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT ); RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer); if ( !NT_SUCCESS(Status) ) { BaseSetLastNTError(Status); return FALSE; } // // Delete the file // #undef DeleteFile Disposition.DeleteFile = TRUE; Status = NtSetInformationFile( Handle, &IoStatusBlock, &Disposition, sizeof(Disposition), FileDispositionInformation ); NtClose(Handle); if ( NT_SUCCESS(Status) ) { return TRUE; } else { BaseSetLastNTError(Status); return FALSE; } }