mirror of
https://github.com/reactos/reactos.git
synced 2025-05-20 17:45:06 +00:00
Improved file attribute and file time handling
svn path=/trunk/; revision=3902
This commit is contained in:
parent
d2d897b1c4
commit
133a166af6
10 changed files with 615 additions and 152 deletions
|
@ -1,4 +1,4 @@
|
|||
/* $Id: finfo.c,v 1.22 2002/11/11 21:49:18 hbirr Exp $
|
||||
/* $Id: finfo.c,v 1.23 2002/12/27 23:50:20 gvg Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -85,6 +85,45 @@ VfatGetPositionInformation(PFILE_OBJECT FileObject,
|
|||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
VfatSetBasicInformation(PFILE_OBJECT FileObject,
|
||||
PVFATFCB FCB,
|
||||
PDEVICE_EXTENSION DeviceExt,
|
||||
PFILE_BASIC_INFORMATION BasicInfo)
|
||||
{
|
||||
DPRINT("VfatSetBasicInformation()\n");
|
||||
|
||||
assert (NULL != FileObject);
|
||||
assert (NULL != FCB);
|
||||
assert (NULL != DeviceExt);
|
||||
assert (NULL != BasicInfo);
|
||||
/* Check volume label bit */
|
||||
assert(0 == (FCB->entry.Attrib & 0x08));
|
||||
|
||||
FsdFileTimeToDosDateTime(&(BasicInfo->CreationTime),
|
||||
&(FCB->entry.CreationDate),
|
||||
&(FCB->entry.CreationTime));
|
||||
FsdFileTimeToDosDateTime(&(BasicInfo->LastAccessTime),
|
||||
&(FCB->entry.AccessDate),
|
||||
NULL);
|
||||
FsdFileTimeToDosDateTime(&(BasicInfo->LastWriteTime),
|
||||
&(FCB->entry.UpdateDate),
|
||||
&(FCB->entry.UpdateTime));
|
||||
|
||||
FCB->entry.Attrib = (FCB->entry.Attrib &
|
||||
(FILE_ATTRIBUTE_DIRECTORY | 0x48)) |
|
||||
(BasicInfo->FileAttributes &
|
||||
(FILE_ATTRIBUTE_ARCHIVE |
|
||||
FILE_ATTRIBUTE_SYSTEM |
|
||||
FILE_ATTRIBUTE_HIDDEN |
|
||||
FILE_ATTRIBUTE_READONLY));
|
||||
DPRINT("Setting attributes 0x%02x\n", FCB->entry.Attrib);
|
||||
|
||||
VfatUpdateEntry(DeviceExt, FileObject);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
VfatGetBasicInformation(PFILE_OBJECT FileObject,
|
||||
PVFATFCB FCB,
|
||||
|
@ -109,7 +148,16 @@ VfatGetBasicInformation(PFILE_OBJECT FileObject,
|
|||
BasicInfo->ChangeTime = BasicInfo->LastWriteTime;
|
||||
|
||||
BasicInfo->FileAttributes = FCB->entry.Attrib;
|
||||
DPRINT("Getting attributes %x\n", BasicInfo->FileAttributes);
|
||||
/* Synthesize FILE_ATTRIBUTE_NORMAL */
|
||||
if (0 == (BasicInfo->FileAttributes & (FILE_ATTRIBUTE_DIRECTORY |
|
||||
FILE_ATTRIBUTE_ARCHIVE |
|
||||
FILE_ATTRIBUTE_SYSTEM |
|
||||
FILE_ATTRIBUTE_HIDDEN |
|
||||
FILE_ATTRIBUTE_READONLY)))
|
||||
{
|
||||
BasicInfo->FileAttributes |= FILE_ATTRIBUTE_NORMAL;
|
||||
}
|
||||
DPRINT("Getting attributes 0x%02x\n", BasicInfo->FileAttributes);
|
||||
|
||||
*BufferLength -= sizeof(FILE_BASIC_INFORMATION);
|
||||
return(STATUS_SUCCESS);
|
||||
|
@ -618,6 +666,11 @@ NTSTATUS VfatSetInformation(PVFAT_IRP_CONTEXT IrpContext)
|
|||
(PLARGE_INTEGER)SystemBuffer);
|
||||
break;
|
||||
case FileBasicInformation:
|
||||
RC = VfatSetBasicInformation(IrpContext->FileObject,
|
||||
FCB,
|
||||
IrpContext->DeviceExt,
|
||||
SystemBuffer);
|
||||
break;
|
||||
case FileRenameInformation:
|
||||
RC = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
|
|
|
@ -638,6 +638,17 @@ CopyFileA(
|
|||
WINBOOL bFailIfExists
|
||||
);
|
||||
|
||||
WINBOOL
|
||||
STDCALL
|
||||
CopyFileExA(
|
||||
LPCSTR lpExistingFileName,
|
||||
LPCSTR lpNewFileName,
|
||||
LPPROGRESS_ROUTINE lpProgressRoutine,
|
||||
LPVOID lpData,
|
||||
LPBOOL pbCancel,
|
||||
DWORD dwCopyFlags
|
||||
);
|
||||
|
||||
WINBOOL
|
||||
STDCALL
|
||||
MoveFileA(
|
||||
|
@ -653,6 +664,16 @@ MoveFileExA(
|
|||
DWORD dwFlags
|
||||
);
|
||||
|
||||
WINBOOL
|
||||
STDCALL
|
||||
MoveFileWithProgressA(
|
||||
LPCSTR lpExistingFileName,
|
||||
LPCSTR lpNewFileName,
|
||||
LPPROGRESS_ROUTINE lpProgressRoutine,
|
||||
LPVOID lpData,
|
||||
DWORD dwFlags
|
||||
);
|
||||
|
||||
HANDLE
|
||||
STDCALL
|
||||
CreateNamedPipeA(
|
||||
|
|
|
@ -4483,6 +4483,21 @@ extern "C" {
|
|||
#define TMPF_TRUETYPE (0x4)
|
||||
#define TMPF_DEVICE (0x8)
|
||||
|
||||
/* CopyFileEx options */
|
||||
#define COPY_FILE_FAIL_IF_EXISTS (1)
|
||||
|
||||
/* CopyProgressRoutine callback */
|
||||
#define CALLBACK_CHUNK_FINISHED (0)
|
||||
#define CALLBACK_STREAM_SWITCH (1)
|
||||
|
||||
#define PROGRESS_CONTINUE (0)
|
||||
#define PROGRESS_CANCEL (1)
|
||||
#define PROGRESS_STOP (2)
|
||||
#define PROGRESS_QUIET (3)
|
||||
|
||||
/* GetFileAttributes */
|
||||
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
|
||||
|
||||
/* --------------------- old stuff, need to organize! --------------- */
|
||||
|
||||
/* BEGINNING of windowsx.h stuff from old headers: */
|
||||
|
|
|
@ -37,6 +37,19 @@
|
|||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef
|
||||
DWORD (CALLBACK *PPROGRESS_ROUTINE)(
|
||||
LARGE_INTEGER TotalFileSize,
|
||||
LARGE_INTEGER TotalBytesTransferred,
|
||||
LARGE_INTEGER StreamSize,
|
||||
LARGE_INTEGER StreamBytesTransferred,
|
||||
DWORD StreamNumber,
|
||||
DWORD CallbackReason,
|
||||
HANDLE SourceFile,
|
||||
HANDLE DestinationFile,
|
||||
LPVOID UserData);
|
||||
typedef PPROGRESS_ROUTINE LPPROGRESS_ROUTINE;
|
||||
|
||||
/* These functions were a real pain, having to figure out which
|
||||
had Unicode/Ascii versions and which did not */
|
||||
|
||||
|
@ -341,8 +354,10 @@ extern "C" {
|
|||
#define FindNextFile FindNextFileW
|
||||
#define SearchPath SearchPathW
|
||||
#define CopyFile CopyFileW
|
||||
#define CopyFileEx CopyFileExW
|
||||
#define MoveFile MoveFileW
|
||||
#define MoveFileEx MoveFileExW
|
||||
#define MoveFileWithProgress MoveFileWithProgressW
|
||||
#define CreateNamedPipe CreateNamedPipeW
|
||||
#define GetNamedPipeHandleState GetNamedPipeHandleStateW
|
||||
#define CallNamedPipe CallNamedPipeW
|
||||
|
@ -745,8 +760,10 @@ extern "C" {
|
|||
#define FindNextFile FindNextFileA
|
||||
#define SearchPath SearchPathA
|
||||
#define CopyFile CopyFileA
|
||||
#define CopyFileEx CopyFileExA
|
||||
#define MoveFile MoveFileA
|
||||
#define MoveFileEx MoveFileExA
|
||||
#define MoveFileWithProgress MoveFileWithProgressA
|
||||
#define CreateNamedPipe CreateNamedPipeA
|
||||
#define GetNamedPipeHandleState GetNamedPipeHandleStateA
|
||||
#define CallNamedPipe CallNamedPipeA
|
||||
|
|
|
@ -639,6 +639,17 @@ CopyFileW(
|
|||
WINBOOL bFailIfExists
|
||||
);
|
||||
|
||||
WINBOOL
|
||||
STDCALL
|
||||
CopyFileExW(
|
||||
LPCWSTR lpExistingFileName,
|
||||
LPCWSTR lpNewFileName,
|
||||
LPPROGRESS_ROUTINE lpProgressRoutine,
|
||||
LPVOID lpData,
|
||||
LPBOOL pbCancel,
|
||||
DWORD dwCopyFlags
|
||||
);
|
||||
|
||||
WINBOOL
|
||||
STDCALL
|
||||
MoveFileW(
|
||||
|
@ -654,6 +665,16 @@ MoveFileExW(
|
|||
DWORD dwFlags
|
||||
);
|
||||
|
||||
WINBOOL
|
||||
STDCALL
|
||||
MoveFileWithProgressW(
|
||||
LPCWSTR lpExistingFileName,
|
||||
LPCWSTR lpNewFileName,
|
||||
LPPROGRESS_ROUTINE lpProgressRoutine,
|
||||
LPVOID lpData,
|
||||
DWORD dwFlags
|
||||
);
|
||||
|
||||
HANDLE
|
||||
STDCALL
|
||||
CreateNamedPipeW(
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: copy.c,v 1.11 2002/09/08 10:22:41 chorns Exp $
|
||||
/* $Id: copy.c,v 1.12 2002/12/27 23:50:21 gvg Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
|
@ -20,11 +20,178 @@
|
|||
#include <kernel32/error.h>
|
||||
|
||||
|
||||
#define LPPROGRESS_ROUTINE void*
|
||||
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
|
||||
static NTSTATUS
|
||||
CopyLoop (
|
||||
HANDLE FileHandleSource,
|
||||
HANDLE FileHandleDest,
|
||||
LARGE_INTEGER SourceFileSize,
|
||||
LPPROGRESS_ROUTINE lpProgressRoutine,
|
||||
LPVOID lpData,
|
||||
WINBOOL *pbCancel,
|
||||
WINBOOL *KeepDest
|
||||
)
|
||||
{
|
||||
NTSTATUS errCode;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
UCHAR *lpBuffer = NULL;
|
||||
ULONG RegionSize = 0x10000;
|
||||
LARGE_INTEGER BytesCopied;
|
||||
DWORD CallbackReason;
|
||||
DWORD ProgressResult;
|
||||
WINBOOL EndOfFileFound;
|
||||
|
||||
*KeepDest = FALSE;
|
||||
errCode = NtAllocateVirtualMemory(NtCurrentProcess(),
|
||||
(PVOID *)&lpBuffer,
|
||||
2,
|
||||
&RegionSize,
|
||||
MEM_RESERVE | MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
|
||||
if (NT_SUCCESS(errCode))
|
||||
{
|
||||
BytesCopied.QuadPart = 0;
|
||||
EndOfFileFound = FALSE;
|
||||
CallbackReason = CALLBACK_STREAM_SWITCH;
|
||||
while (! EndOfFileFound &&
|
||||
NT_SUCCESS(errCode) &&
|
||||
(NULL == pbCancel || ! *pbCancel))
|
||||
{
|
||||
if (NULL != lpProgressRoutine)
|
||||
{
|
||||
ProgressResult = (*lpProgressRoutine)(SourceFileSize,
|
||||
BytesCopied,
|
||||
SourceFileSize,
|
||||
BytesCopied,
|
||||
0,
|
||||
CallbackReason,
|
||||
FileHandleSource,
|
||||
FileHandleDest,
|
||||
lpData);
|
||||
switch (ProgressResult)
|
||||
{
|
||||
case PROGRESS_CANCEL:
|
||||
DPRINT("Progress callback requested cancel\n");
|
||||
errCode = STATUS_REQUEST_ABORTED;
|
||||
break;
|
||||
case PROGRESS_STOP:
|
||||
DPRINT("Progress callback requested stop\n");
|
||||
errCode = STATUS_REQUEST_ABORTED;
|
||||
*KeepDest = TRUE;
|
||||
break;
|
||||
case PROGRESS_QUIET:
|
||||
lpProgressRoutine = NULL;
|
||||
break;
|
||||
case PROGRESS_CONTINUE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
CallbackReason = CALLBACK_CHUNK_FINISHED;
|
||||
}
|
||||
if (NT_SUCCESS(errCode))
|
||||
{
|
||||
errCode = NtReadFile(FileHandleSource,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
(PIO_STATUS_BLOCK)&IoStatusBlock,
|
||||
lpBuffer,
|
||||
RegionSize,
|
||||
NULL,
|
||||
NULL);
|
||||
if (NT_SUCCESS(errCode) && (NULL == pbCancel || ! *pbCancel))
|
||||
{
|
||||
errCode = NtWriteFile(FileHandleDest,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
(PIO_STATUS_BLOCK)&IoStatusBlock,
|
||||
lpBuffer,
|
||||
IoStatusBlock.Information,
|
||||
NULL,
|
||||
NULL);
|
||||
if (NT_SUCCESS(errCode))
|
||||
{
|
||||
BytesCopied.QuadPart += IoStatusBlock.Information;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("Error 0x%08x reading writing to dest\n", errCode);
|
||||
}
|
||||
}
|
||||
else if (!NT_SUCCESS(errCode))
|
||||
{
|
||||
if (STATUS_END_OF_FILE == errCode)
|
||||
{
|
||||
EndOfFileFound = TRUE;
|
||||
errCode = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("Error 0x%08x reading from source\n", errCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! EndOfFileFound && (NULL != pbCancel && *pbCancel))
|
||||
{
|
||||
DPRINT("User requested cancel\n");
|
||||
errCode = STATUS_REQUEST_ABORTED;
|
||||
}
|
||||
|
||||
NtFreeVirtualMemory(NtCurrentProcess(),
|
||||
(PVOID *)&lpBuffer,
|
||||
&RegionSize,
|
||||
MEM_RELEASE);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("Error 0x%08x allocating buffer of %d bytes\n", errCode, RegionSize);
|
||||
}
|
||||
|
||||
return errCode;
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
SetLastWriteTime(
|
||||
HANDLE FileHandle,
|
||||
TIME 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))
|
||||
{
|
||||
DPRINT("Error 0x%08x obtaining FileBasicInformation\n", errCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileBasic.LastWriteTime = LastWriteTime;
|
||||
errCode = NtSetInformationFile (FileHandle,
|
||||
&IoStatusBlock,
|
||||
&FileBasic,
|
||||
sizeof(FILE_BASIC_INFORMATION),
|
||||
FileBasicInformation);
|
||||
if (!NT_SUCCESS(errCode))
|
||||
{
|
||||
DPRINT("Error 0x%0x setting LastWriteTime\n", errCode);
|
||||
}
|
||||
}
|
||||
|
||||
return errCode;
|
||||
}
|
||||
|
||||
WINBOOL
|
||||
STDCALL
|
||||
CopyFileExW (
|
||||
|
@ -36,15 +203,15 @@ CopyFileExW (
|
|||
DWORD dwCopyFlags
|
||||
)
|
||||
{
|
||||
NTSTATUS errCode = 0;
|
||||
NTSTATUS errCode;
|
||||
HANDLE FileHandleSource, FileHandleDest;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
FILE_STANDARD_INFORMATION FileStandard;
|
||||
FILE_BASIC_INFORMATION FileBasic;
|
||||
FILE_POSITION_INFORMATION FilePosition;
|
||||
UCHAR *lpBuffer = NULL;
|
||||
ULONG RegionSize = 0x1000000;
|
||||
BOOL bCancel = FALSE;
|
||||
FILE_DISPOSITION_INFORMATION FileDispInfo;
|
||||
WINBOOL RC = FALSE;
|
||||
WINBOOL KeepDestOnError = FALSE;
|
||||
DWORD SystemError;
|
||||
|
||||
FileHandleSource = CreateFileW(lpExistingFileName,
|
||||
GENERIC_READ,
|
||||
|
@ -53,137 +220,87 @@ CopyFileExW (
|
|||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_NO_BUFFERING,
|
||||
NULL);
|
||||
if (FileHandleSource == NULL)
|
||||
{
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
errCode = NtQueryInformationFile(FileHandleSource,
|
||||
&IoStatusBlock,
|
||||
&FileStandard,
|
||||
sizeof(FILE_STANDARD_INFORMATION),
|
||||
FileStandardInformation);
|
||||
if (!NT_SUCCESS(errCode))
|
||||
if (INVALID_HANDLE_VALUE != FileHandleSource)
|
||||
{
|
||||
errCode = NtQueryInformationFile(FileHandleSource,
|
||||
&IoStatusBlock,
|
||||
&FileStandard,
|
||||
sizeof(FILE_STANDARD_INFORMATION),
|
||||
FileStandardInformation);
|
||||
if (!NT_SUCCESS(errCode))
|
||||
{
|
||||
DPRINT("Status 0x%08x obtaining FileStandardInformation for source\n", errCode);
|
||||
SetLastErrorByStatus(errCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
errCode = NtQueryInformationFile(FileHandleSource,
|
||||
&IoStatusBlock,&FileBasic,
|
||||
sizeof(FILE_BASIC_INFORMATION),
|
||||
FileBasicInformation);
|
||||
if (!NT_SUCCESS(errCode))
|
||||
{
|
||||
DPRINT("Status 0x%08x obtaining FileBasicInformation for source\n", errCode);
|
||||
SetLastErrorByStatus(errCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileHandleDest = CreateFileW(lpNewFileName,
|
||||
GENERIC_WRITE,
|
||||
FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
dwCopyFlags ? CREATE_NEW : CREATE_ALWAYS,
|
||||
FileBasic.FileAttributes,
|
||||
NULL);
|
||||
if (INVALID_HANDLE_VALUE != FileHandleDest)
|
||||
{
|
||||
errCode = CopyLoop(FileHandleSource,
|
||||
FileHandleDest,
|
||||
FileStandard.EndOfFile,
|
||||
lpProgressRoutine,
|
||||
lpData,
|
||||
pbCancel,
|
||||
&KeepDestOnError);
|
||||
if (!NT_SUCCESS(errCode))
|
||||
{
|
||||
SetLastErrorByStatus(errCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
errCode = SetLastWriteTime(FileHandleDest,
|
||||
FileBasic.LastWriteTime);
|
||||
if (!NT_SUCCESS(errCode))
|
||||
{
|
||||
SetLastErrorByStatus(errCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
RC = TRUE;
|
||||
}
|
||||
}
|
||||
NtClose(FileHandleDest);
|
||||
if (! RC && ! KeepDestOnError)
|
||||
{
|
||||
SystemError = GetLastError();
|
||||
SetFileAttributesW(lpNewFileName, FILE_ATTRIBUTE_NORMAL);
|
||||
DeleteFileW(lpNewFileName);
|
||||
SetLastError(SystemError);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("Error %d during opening of dest file\n", GetLastError());
|
||||
}
|
||||
}
|
||||
}
|
||||
NtClose(FileHandleSource);
|
||||
SetLastErrorByStatus(errCode);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
errCode = NtQueryInformationFile(FileHandleSource,
|
||||
&IoStatusBlock,&FileBasic,
|
||||
sizeof(FILE_BASIC_INFORMATION),
|
||||
FileBasicInformation);
|
||||
if (!NT_SUCCESS(errCode))
|
||||
else
|
||||
{
|
||||
NtClose(FileHandleSource);
|
||||
SetLastErrorByStatus(errCode);
|
||||
return FALSE;
|
||||
DPRINT("Error %d during opening of source file\n", GetLastError());
|
||||
}
|
||||
|
||||
FileHandleDest = CreateFileW(lpNewFileName,
|
||||
GENERIC_WRITE,
|
||||
FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
dwCopyFlags ? CREATE_NEW : CREATE_ALWAYS,
|
||||
FileBasic.FileAttributes|FILE_FLAG_NO_BUFFERING,
|
||||
NULL);
|
||||
if (FileHandleDest == NULL)
|
||||
{
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
FilePosition.CurrentByteOffset.QuadPart = 0;
|
||||
|
||||
errCode = NtSetInformationFile(FileHandleSource,
|
||||
&IoStatusBlock,
|
||||
&FilePosition,
|
||||
sizeof(FILE_POSITION_INFORMATION),
|
||||
FilePositionInformation);
|
||||
if (!NT_SUCCESS(errCode))
|
||||
{
|
||||
NtClose(FileHandleSource);
|
||||
NtClose(FileHandleDest);
|
||||
SetLastErrorByStatus(errCode);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
errCode = NtSetInformationFile(FileHandleDest,
|
||||
&IoStatusBlock,
|
||||
&FilePosition,
|
||||
sizeof(FILE_POSITION_INFORMATION),
|
||||
FilePositionInformation);
|
||||
if (!NT_SUCCESS(errCode))
|
||||
{
|
||||
NtClose(FileHandleSource);
|
||||
NtClose(FileHandleDest);
|
||||
SetLastErrorByStatus(errCode);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
errCode = NtAllocateVirtualMemory(NtCurrentProcess(),
|
||||
(PVOID *)&lpBuffer,
|
||||
2,
|
||||
&RegionSize,
|
||||
MEM_RESERVE | MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
|
||||
if (!NT_SUCCESS(errCode))
|
||||
{
|
||||
NtClose(FileHandleSource);
|
||||
NtClose(FileHandleDest);
|
||||
SetLastErrorByStatus(errCode);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
do {
|
||||
errCode = NtReadFile(FileHandleSource,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
(PIO_STATUS_BLOCK)&IoStatusBlock,
|
||||
lpBuffer,
|
||||
RegionSize,
|
||||
NULL,
|
||||
NULL);
|
||||
if (pbCancel != NULL)
|
||||
bCancel = *pbCancel;
|
||||
|
||||
if (!NT_SUCCESS(errCode) || bCancel)
|
||||
{
|
||||
NtFreeVirtualMemory(NtCurrentProcess(),
|
||||
(PVOID *)&lpBuffer, &RegionSize,MEM_RELEASE);
|
||||
NtClose(FileHandleSource);
|
||||
NtClose(FileHandleDest);
|
||||
if ( errCode == STATUS_END_OF_FILE )
|
||||
break;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
errCode = NtWriteFile(FileHandleDest,
|
||||
NULL,
|
||||
lpProgressRoutine,
|
||||
lpData,
|
||||
(PIO_STATUS_BLOCK)&IoStatusBlock,
|
||||
lpBuffer,
|
||||
IoStatusBlock.Information,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (!NT_SUCCESS(errCode))
|
||||
{
|
||||
NtFreeVirtualMemory(NtCurrentProcess(),
|
||||
(PVOID *)&lpBuffer,
|
||||
&RegionSize,
|
||||
MEM_RELEASE);
|
||||
NtClose(FileHandleSource);
|
||||
NtClose(FileHandleDest);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
} while ( TRUE );
|
||||
return TRUE;
|
||||
return RC;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: file.c,v 1.38 2002/11/07 02:52:37 robd Exp $
|
||||
/* $Id: file.c,v 1.39 2002/12/27 23:50:21 gvg Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
|
@ -21,8 +21,6 @@
|
|||
#include <kernel32/kernel32.h>
|
||||
#include <kernel32/error.h>
|
||||
|
||||
#define LPPROGRESS_ROUTINE void*
|
||||
|
||||
|
||||
/* GLOBALS ******************************************************************/
|
||||
|
||||
|
@ -607,6 +605,11 @@ SetFileAttributesW(LPCWSTR lpFileName,
|
|||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (INVALID_HANDLE_VALUE == hFile)
|
||||
{
|
||||
DPRINT("SetFileAttributes CreateFileW failed with code %d\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
errCode = NtQueryInformationFile(hFile,
|
||||
&IoStatusBlock,
|
||||
|
@ -616,6 +619,7 @@ SetFileAttributesW(LPCWSTR lpFileName,
|
|||
if (!NT_SUCCESS(errCode))
|
||||
{
|
||||
CloseHandle(hFile);
|
||||
DPRINT("SetFileAttributes NtQueryInformationFile failed with status 0x%08x\n", errCode);
|
||||
SetLastErrorByStatus(errCode);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -628,6 +632,7 @@ SetFileAttributesW(LPCWSTR lpFileName,
|
|||
if (!NT_SUCCESS(errCode))
|
||||
{
|
||||
CloseHandle(hFile);
|
||||
DPRINT("SetFileAttributes NtSetInformationFile failed with status 0x%08x\n", errCode);
|
||||
SetLastErrorByStatus(errCode);
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: move.c,v 1.7 2002/09/08 10:22:42 chorns Exp $
|
||||
/* $Id: move.c,v 1.8 2002/12/27 23:50:21 gvg Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
|
@ -17,6 +17,7 @@
|
|||
|
||||
#define NDEBUG
|
||||
#include <kernel32/kernel32.h>
|
||||
#include <kernel32/error.h>
|
||||
|
||||
|
||||
#define FILE_RENAME_SIZE MAX_PATH +sizeof(FILE_RENAME_INFORMATION)
|
||||
|
@ -44,6 +45,24 @@ MoveFileExA (
|
|||
LPCSTR lpNewFileName,
|
||||
DWORD dwFlags
|
||||
)
|
||||
{
|
||||
return MoveFileWithProgressA (lpExistingFileName,
|
||||
lpNewFileName,
|
||||
NULL,
|
||||
NULL,
|
||||
dwFlags);
|
||||
}
|
||||
|
||||
|
||||
WINBOOL
|
||||
STDCALL
|
||||
MoveFileWithProgressA (
|
||||
LPCSTR lpExistingFileName,
|
||||
LPCSTR lpNewFileName,
|
||||
LPPROGRESS_ROUTINE lpProgressRoutine,
|
||||
LPVOID lpData,
|
||||
DWORD dwFlags
|
||||
)
|
||||
{
|
||||
UNICODE_STRING ExistingFileNameU;
|
||||
UNICODE_STRING NewFileNameU;
|
||||
|
@ -77,9 +96,11 @@ MoveFileExA (
|
|||
TRUE);
|
||||
}
|
||||
|
||||
Result = MoveFileExW (ExistingFileNameU.Buffer,
|
||||
NewFileNameU.Buffer,
|
||||
dwFlags);
|
||||
Result = MoveFileWithProgressW (ExistingFileNameU.Buffer,
|
||||
NewFileNameU.Buffer,
|
||||
lpProgressRoutine,
|
||||
lpData,
|
||||
dwFlags);
|
||||
|
||||
RtlFreeHeap (RtlGetProcessHeap (),
|
||||
0,
|
||||
|
@ -112,12 +133,159 @@ MoveFileExW (
|
|||
LPCWSTR lpNewFileName,
|
||||
DWORD dwFlags
|
||||
)
|
||||
{
|
||||
return MoveFileWithProgressW (lpExistingFileName,
|
||||
lpNewFileName,
|
||||
NULL,
|
||||
NULL,
|
||||
dwFlags);
|
||||
}
|
||||
|
||||
|
||||
static WINBOOL
|
||||
AdjustFileAttributes (
|
||||
LPCWSTR ExistingFileName,
|
||||
LPCWSTR NewFileName
|
||||
)
|
||||
{
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
FILE_BASIC_INFORMATION ExistingInfo,
|
||||
NewInfo;
|
||||
HANDLE hFile;
|
||||
DWORD Attributes;
|
||||
NTSTATUS errCode;
|
||||
WINBOOL Result = FALSE;
|
||||
|
||||
hFile = CreateFileW (ExistingFileName,
|
||||
FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (INVALID_HANDLE_VALUE != hFile)
|
||||
{
|
||||
errCode = NtQueryInformationFile (hFile,
|
||||
&IoStatusBlock,
|
||||
&ExistingInfo,
|
||||
sizeof(FILE_BASIC_INFORMATION),
|
||||
FileBasicInformation);
|
||||
if (NT_SUCCESS (errCode))
|
||||
{
|
||||
if (0 != (ExistingInfo.FileAttributes & FILE_ATTRIBUTE_READONLY))
|
||||
{
|
||||
Attributes = ExistingInfo.FileAttributes;
|
||||
ExistingInfo.FileAttributes &= ~ FILE_ATTRIBUTE_READONLY;
|
||||
if (0 == (ExistingInfo.FileAttributes &
|
||||
(FILE_ATTRIBUTE_HIDDEN |
|
||||
FILE_ATTRIBUTE_SYSTEM |
|
||||
FILE_ATTRIBUTE_ARCHIVE)))
|
||||
{
|
||||
ExistingInfo.FileAttributes |= FILE_ATTRIBUTE_NORMAL;
|
||||
}
|
||||
errCode = NtSetInformationFile (hFile,
|
||||
&IoStatusBlock,
|
||||
&ExistingInfo,
|
||||
sizeof(FILE_BASIC_INFORMATION),
|
||||
FileBasicInformation);
|
||||
if (!NT_SUCCESS(errCode))
|
||||
{
|
||||
DPRINT("Removing READONLY attribute from source failed with status 0x%08x\n", errCode);
|
||||
}
|
||||
ExistingInfo.FileAttributes = Attributes;
|
||||
}
|
||||
CloseHandle(hFile);
|
||||
|
||||
if (NT_SUCCESS(errCode))
|
||||
{
|
||||
hFile = CreateFileW (NewFileName,
|
||||
FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (INVALID_HANDLE_VALUE != hFile)
|
||||
{
|
||||
errCode = NtQueryInformationFile(hFile,
|
||||
&IoStatusBlock,
|
||||
&NewInfo,
|
||||
sizeof(FILE_BASIC_INFORMATION),
|
||||
FileBasicInformation);
|
||||
if (NT_SUCCESS(errCode))
|
||||
{
|
||||
NewInfo.FileAttributes = (NewInfo.FileAttributes &
|
||||
~ (FILE_ATTRIBUTE_HIDDEN |
|
||||
FILE_ATTRIBUTE_SYSTEM |
|
||||
FILE_ATTRIBUTE_READONLY |
|
||||
FILE_ATTRIBUTE_NORMAL)) |
|
||||
(ExistingInfo.FileAttributes &
|
||||
(FILE_ATTRIBUTE_HIDDEN |
|
||||
FILE_ATTRIBUTE_SYSTEM |
|
||||
FILE_ATTRIBUTE_READONLY |
|
||||
FILE_ATTRIBUTE_NORMAL)) |
|
||||
FILE_ATTRIBUTE_ARCHIVE;
|
||||
NewInfo.CreationTime = ExistingInfo.CreationTime;
|
||||
NewInfo.LastAccessTime = ExistingInfo.LastAccessTime;
|
||||
NewInfo.LastWriteTime = ExistingInfo.LastWriteTime;
|
||||
errCode = NtSetInformationFile (hFile,
|
||||
&IoStatusBlock,
|
||||
&NewInfo,
|
||||
sizeof(FILE_BASIC_INFORMATION),
|
||||
FileBasicInformation);
|
||||
if (NT_SUCCESS(errCode))
|
||||
{
|
||||
Result = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("Setting attributes on dest file failed with status 0x%08x\n", errCode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("Obtaining attributes from dest file failed with status 0x%08x\n", errCode);
|
||||
}
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("Opening dest file to set attributes failed with code %d\n", GetLastError());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("Obtaining attributes from source file failed with status 0x%08x\n", errCode);
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("Opening source file to obtain attributes failed with code %d\n", GetLastError());
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
WINBOOL
|
||||
STDCALL
|
||||
MoveFileWithProgressW (
|
||||
LPCWSTR lpExistingFileName,
|
||||
LPCWSTR lpNewFileName,
|
||||
LPPROGRESS_ROUTINE lpProgressRoutine,
|
||||
LPVOID lpData,
|
||||
DWORD dwFlags
|
||||
)
|
||||
{
|
||||
HANDLE hFile = NULL;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
FILE_RENAME_INFORMATION *FileRename;
|
||||
USHORT Buffer[FILE_RENAME_SIZE];
|
||||
NTSTATUS errCode;
|
||||
NTSTATUS errCode;
|
||||
DWORD err;
|
||||
WINBOOL Result;
|
||||
|
||||
hFile = CreateFileW (lpExistingFileName,
|
||||
GENERIC_ALL,
|
||||
|
@ -137,21 +305,63 @@ MoveFileExW (
|
|||
memcpy (FileRename->FileName,
|
||||
lpNewFileName,
|
||||
min(FileRename->FileNameLength, MAX_PATH));
|
||||
|
||||
|
||||
errCode = NtSetInformationFile (hFile,
|
||||
&IoStatusBlock,
|
||||
FileRename,
|
||||
FILE_RENAME_SIZE,
|
||||
FileRenameInformation);
|
||||
CloseHandle(hFile);
|
||||
if (!NT_SUCCESS(errCode))
|
||||
if (NT_SUCCESS(errCode))
|
||||
{
|
||||
if (CopyFileW (lpExistingFileName,
|
||||
lpNewFileName,
|
||||
FileRename->Replace))
|
||||
DeleteFileW (lpExistingFileName);
|
||||
Result = TRUE;
|
||||
}
|
||||
return TRUE;
|
||||
/* FIXME file rename not yet implemented in all FSDs so it will always
|
||||
* fail, even when the move is to the same device
|
||||
*/
|
||||
#if 0
|
||||
else if (STATUS_NOT_SAME_DEVICE == errCode &&
|
||||
MOVEFILE_COPY_ALLOWED == (dwFlags & MOVEFILE_COPY_ALLOWED))
|
||||
#else
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Result = CopyFileExW (lpExistingFileName,
|
||||
lpNewFileName,
|
||||
lpProgressRoutine,
|
||||
lpData,
|
||||
NULL,
|
||||
FileRename->Replace ? 0 : COPY_FILE_FAIL_IF_EXISTS) &&
|
||||
AdjustFileAttributes(lpExistingFileName, lpNewFileName) &&
|
||||
DeleteFileW (lpExistingFileName);
|
||||
if (! Result)
|
||||
{
|
||||
/* Delete of the existing file failed so the
|
||||
* existing file is still there. Clean up the
|
||||
* new file (if possible)
|
||||
*/
|
||||
err = GetLastError();
|
||||
if (! SetFileAttributesW (lpNewFileName, FILE_ATTRIBUTE_NORMAL))
|
||||
{
|
||||
DPRINT("Removing possible READONLY attrib from new file failed with code %d\n", GetLastError());
|
||||
}
|
||||
if (! DeleteFileW (lpNewFileName))
|
||||
{
|
||||
DPRINT("Deleting new file during cleanup failed with code %d\n", GetLastError());
|
||||
}
|
||||
SetLastError (err);
|
||||
}
|
||||
}
|
||||
/* See FIXME above */
|
||||
#if 0
|
||||
else
|
||||
{
|
||||
SetLastErrorByStatus (errCode);
|
||||
Result = FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -449,8 +449,10 @@ MapViewOfFile@20
|
|||
MapViewOfFileEx@24
|
||||
MoveFileA@8
|
||||
MoveFileExA@12
|
||||
MoveFileWithProgressA@20
|
||||
MoveFileExW@12
|
||||
MoveFileW@8
|
||||
MoveFileWithProgressW@20
|
||||
MulDiv@12
|
||||
MultiByteToWideChar@24
|
||||
OpenConsoleW@16
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; $Id: kernel32.edf,v 1.16 2002/11/12 00:46:02 mdill Exp $
|
||||
; $Id: kernel32.edf,v 1.17 2002/12/27 23:50:20 gvg Exp $
|
||||
;
|
||||
; kernel32.edf
|
||||
;
|
||||
|
@ -453,8 +453,10 @@ MapViewOfFile=MapViewOfFile@20
|
|||
MapViewOfFileEx=MapViewOfFileEx@24
|
||||
MoveFileA=MoveFileA@8
|
||||
MoveFileExA=MoveFileExA@12
|
||||
MoveFileWithProgressA=MoveFileWithProgressA@20
|
||||
MoveFileExW=MoveFileExW@12
|
||||
MoveFileW=MoveFileW@8
|
||||
MoveFileWithProgressW=MoveFileWithProgressW@20
|
||||
MulDiv=MulDiv@12
|
||||
MultiByteToWideChar=MultiByteToWideChar@24
|
||||
OpenConsoleW=OpenConsoleW@16
|
||||
|
|
Loading…
Reference in a new issue