Improved file attribute and file time handling

svn path=/trunk/; revision=3902
This commit is contained in:
Gé van Geldorp 2002-12-27 23:50:21 +00:00
parent d2d897b1c4
commit 133a166af6
10 changed files with 615 additions and 152 deletions

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -85,6 +85,45 @@ VfatGetPositionInformation(PFILE_OBJECT FileObject,
return(STATUS_SUCCESS); 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 static NTSTATUS
VfatGetBasicInformation(PFILE_OBJECT FileObject, VfatGetBasicInformation(PFILE_OBJECT FileObject,
PVFATFCB FCB, PVFATFCB FCB,
@ -109,7 +148,16 @@ VfatGetBasicInformation(PFILE_OBJECT FileObject,
BasicInfo->ChangeTime = BasicInfo->LastWriteTime; BasicInfo->ChangeTime = BasicInfo->LastWriteTime;
BasicInfo->FileAttributes = FCB->entry.Attrib; 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); *BufferLength -= sizeof(FILE_BASIC_INFORMATION);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
@ -618,6 +666,11 @@ NTSTATUS VfatSetInformation(PVFAT_IRP_CONTEXT IrpContext)
(PLARGE_INTEGER)SystemBuffer); (PLARGE_INTEGER)SystemBuffer);
break; break;
case FileBasicInformation: case FileBasicInformation:
RC = VfatSetBasicInformation(IrpContext->FileObject,
FCB,
IrpContext->DeviceExt,
SystemBuffer);
break;
case FileRenameInformation: case FileRenameInformation:
RC = STATUS_NOT_IMPLEMENTED; RC = STATUS_NOT_IMPLEMENTED;
break; break;

View file

@ -638,6 +638,17 @@ CopyFileA(
WINBOOL bFailIfExists WINBOOL bFailIfExists
); );
WINBOOL
STDCALL
CopyFileExA(
LPCSTR lpExistingFileName,
LPCSTR lpNewFileName,
LPPROGRESS_ROUTINE lpProgressRoutine,
LPVOID lpData,
LPBOOL pbCancel,
DWORD dwCopyFlags
);
WINBOOL WINBOOL
STDCALL STDCALL
MoveFileA( MoveFileA(
@ -653,6 +664,16 @@ MoveFileExA(
DWORD dwFlags DWORD dwFlags
); );
WINBOOL
STDCALL
MoveFileWithProgressA(
LPCSTR lpExistingFileName,
LPCSTR lpNewFileName,
LPPROGRESS_ROUTINE lpProgressRoutine,
LPVOID lpData,
DWORD dwFlags
);
HANDLE HANDLE
STDCALL STDCALL
CreateNamedPipeA( CreateNamedPipeA(

View file

@ -4483,6 +4483,21 @@ extern "C" {
#define TMPF_TRUETYPE (0x4) #define TMPF_TRUETYPE (0x4)
#define TMPF_DEVICE (0x8) #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! --------------- */ /* --------------------- old stuff, need to organize! --------------- */
/* BEGINNING of windowsx.h stuff from old headers: */ /* BEGINNING of windowsx.h stuff from old headers: */

View file

@ -37,6 +37,19 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #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 /* These functions were a real pain, having to figure out which
had Unicode/Ascii versions and which did not */ had Unicode/Ascii versions and which did not */
@ -341,8 +354,10 @@ extern "C" {
#define FindNextFile FindNextFileW #define FindNextFile FindNextFileW
#define SearchPath SearchPathW #define SearchPath SearchPathW
#define CopyFile CopyFileW #define CopyFile CopyFileW
#define CopyFileEx CopyFileExW
#define MoveFile MoveFileW #define MoveFile MoveFileW
#define MoveFileEx MoveFileExW #define MoveFileEx MoveFileExW
#define MoveFileWithProgress MoveFileWithProgressW
#define CreateNamedPipe CreateNamedPipeW #define CreateNamedPipe CreateNamedPipeW
#define GetNamedPipeHandleState GetNamedPipeHandleStateW #define GetNamedPipeHandleState GetNamedPipeHandleStateW
#define CallNamedPipe CallNamedPipeW #define CallNamedPipe CallNamedPipeW
@ -745,8 +760,10 @@ extern "C" {
#define FindNextFile FindNextFileA #define FindNextFile FindNextFileA
#define SearchPath SearchPathA #define SearchPath SearchPathA
#define CopyFile CopyFileA #define CopyFile CopyFileA
#define CopyFileEx CopyFileExA
#define MoveFile MoveFileA #define MoveFile MoveFileA
#define MoveFileEx MoveFileExA #define MoveFileEx MoveFileExA
#define MoveFileWithProgress MoveFileWithProgressA
#define CreateNamedPipe CreateNamedPipeA #define CreateNamedPipe CreateNamedPipeA
#define GetNamedPipeHandleState GetNamedPipeHandleStateA #define GetNamedPipeHandleState GetNamedPipeHandleStateA
#define CallNamedPipe CallNamedPipeA #define CallNamedPipe CallNamedPipeA

View file

@ -639,6 +639,17 @@ CopyFileW(
WINBOOL bFailIfExists WINBOOL bFailIfExists
); );
WINBOOL
STDCALL
CopyFileExW(
LPCWSTR lpExistingFileName,
LPCWSTR lpNewFileName,
LPPROGRESS_ROUTINE lpProgressRoutine,
LPVOID lpData,
LPBOOL pbCancel,
DWORD dwCopyFlags
);
WINBOOL WINBOOL
STDCALL STDCALL
MoveFileW( MoveFileW(
@ -654,6 +665,16 @@ MoveFileExW(
DWORD dwFlags DWORD dwFlags
); );
WINBOOL
STDCALL
MoveFileWithProgressW(
LPCWSTR lpExistingFileName,
LPCWSTR lpNewFileName,
LPPROGRESS_ROUTINE lpProgressRoutine,
LPVOID lpData,
DWORD dwFlags
);
HANDLE HANDLE
STDCALL STDCALL
CreateNamedPipeW( CreateNamedPipeW(

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries * PROJECT: ReactOS system libraries
@ -20,11 +20,178 @@
#include <kernel32/error.h> #include <kernel32/error.h>
#define LPPROGRESS_ROUTINE void*
/* FUNCTIONS ****************************************************************/ /* 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 WINBOOL
STDCALL STDCALL
CopyFileExW ( CopyFileExW (
@ -36,15 +203,15 @@ CopyFileExW (
DWORD dwCopyFlags DWORD dwCopyFlags
) )
{ {
NTSTATUS errCode = 0; NTSTATUS errCode;
HANDLE FileHandleSource, FileHandleDest; HANDLE FileHandleSource, FileHandleDest;
IO_STATUS_BLOCK IoStatusBlock; IO_STATUS_BLOCK IoStatusBlock;
FILE_STANDARD_INFORMATION FileStandard; FILE_STANDARD_INFORMATION FileStandard;
FILE_BASIC_INFORMATION FileBasic; FILE_BASIC_INFORMATION FileBasic;
FILE_POSITION_INFORMATION FilePosition; FILE_DISPOSITION_INFORMATION FileDispInfo;
UCHAR *lpBuffer = NULL; WINBOOL RC = FALSE;
ULONG RegionSize = 0x1000000; WINBOOL KeepDestOnError = FALSE;
BOOL bCancel = FALSE; DWORD SystemError;
FileHandleSource = CreateFileW(lpExistingFileName, FileHandleSource = CreateFileW(lpExistingFileName,
GENERIC_READ, GENERIC_READ,
@ -53,11 +220,8 @@ CopyFileExW (
OPEN_EXISTING, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_NO_BUFFERING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_NO_BUFFERING,
NULL); NULL);
if (FileHandleSource == NULL) if (INVALID_HANDLE_VALUE != FileHandleSource)
{ {
return(FALSE);
}
errCode = NtQueryInformationFile(FileHandleSource, errCode = NtQueryInformationFile(FileHandleSource,
&IoStatusBlock, &IoStatusBlock,
&FileStandard, &FileStandard,
@ -65,125 +229,78 @@ CopyFileExW (
FileStandardInformation); FileStandardInformation);
if (!NT_SUCCESS(errCode)) if (!NT_SUCCESS(errCode))
{ {
NtClose(FileHandleSource); DPRINT("Status 0x%08x obtaining FileStandardInformation for source\n", errCode);
SetLastErrorByStatus(errCode); SetLastErrorByStatus(errCode);
return FALSE;
} }
else
{
errCode = NtQueryInformationFile(FileHandleSource, errCode = NtQueryInformationFile(FileHandleSource,
&IoStatusBlock,&FileBasic, &IoStatusBlock,&FileBasic,
sizeof(FILE_BASIC_INFORMATION), sizeof(FILE_BASIC_INFORMATION),
FileBasicInformation); FileBasicInformation);
if (!NT_SUCCESS(errCode)) if (!NT_SUCCESS(errCode))
{ {
NtClose(FileHandleSource); DPRINT("Status 0x%08x obtaining FileBasicInformation for source\n", errCode);
SetLastErrorByStatus(errCode); SetLastErrorByStatus(errCode);
return FALSE;
} }
else
{
FileHandleDest = CreateFileW(lpNewFileName, FileHandleDest = CreateFileW(lpNewFileName,
GENERIC_WRITE, GENERIC_WRITE,
FILE_SHARE_WRITE, FILE_SHARE_WRITE,
NULL, NULL,
dwCopyFlags ? CREATE_NEW : CREATE_ALWAYS, dwCopyFlags ? CREATE_NEW : CREATE_ALWAYS,
FileBasic.FileAttributes|FILE_FLAG_NO_BUFFERING, FileBasic.FileAttributes,
NULL); NULL);
if (FileHandleDest == NULL) if (INVALID_HANDLE_VALUE != FileHandleDest)
{ {
return(FALSE); errCode = CopyLoop(FileHandleSource,
} FileHandleDest,
FileStandard.EndOfFile,
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, lpProgressRoutine,
lpData, lpData,
(PIO_STATUS_BLOCK)&IoStatusBlock, pbCancel,
lpBuffer, &KeepDestOnError);
IoStatusBlock.Information,
NULL,
NULL);
if (!NT_SUCCESS(errCode)) if (!NT_SUCCESS(errCode))
{ {
NtFreeVirtualMemory(NtCurrentProcess(), SetLastErrorByStatus(errCode);
(PVOID *)&lpBuffer, }
&RegionSize, else
MEM_RELEASE); {
NtClose(FileHandleSource); errCode = SetLastWriteTime(FileHandleDest,
FileBasic.LastWriteTime);
if (!NT_SUCCESS(errCode))
{
SetLastErrorByStatus(errCode);
}
else
{
RC = TRUE;
}
}
NtClose(FileHandleDest); NtClose(FileHandleDest);
return FALSE; 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);
}
else
{
DPRINT("Error %d during opening of source file\n", GetLastError());
} }
} while ( TRUE ); return RC;
return TRUE;
} }

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries * PROJECT: ReactOS system libraries
@ -21,8 +21,6 @@
#include <kernel32/kernel32.h> #include <kernel32/kernel32.h>
#include <kernel32/error.h> #include <kernel32/error.h>
#define LPPROGRESS_ROUTINE void*
/* GLOBALS ******************************************************************/ /* GLOBALS ******************************************************************/
@ -607,6 +605,11 @@ SetFileAttributesW(LPCWSTR lpFileName,
OPEN_EXISTING, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL,
NULL); NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
DPRINT("SetFileAttributes CreateFileW failed with code %d\n", GetLastError());
return FALSE;
}
errCode = NtQueryInformationFile(hFile, errCode = NtQueryInformationFile(hFile,
&IoStatusBlock, &IoStatusBlock,
@ -616,6 +619,7 @@ SetFileAttributesW(LPCWSTR lpFileName,
if (!NT_SUCCESS(errCode)) if (!NT_SUCCESS(errCode))
{ {
CloseHandle(hFile); CloseHandle(hFile);
DPRINT("SetFileAttributes NtQueryInformationFile failed with status 0x%08x\n", errCode);
SetLastErrorByStatus(errCode); SetLastErrorByStatus(errCode);
return FALSE; return FALSE;
} }
@ -628,6 +632,7 @@ SetFileAttributesW(LPCWSTR lpFileName,
if (!NT_SUCCESS(errCode)) if (!NT_SUCCESS(errCode))
{ {
CloseHandle(hFile); CloseHandle(hFile);
DPRINT("SetFileAttributes NtSetInformationFile failed with status 0x%08x\n", errCode);
SetLastErrorByStatus(errCode); SetLastErrorByStatus(errCode);
return FALSE; return FALSE;
} }

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries * PROJECT: ReactOS system libraries
@ -17,6 +17,7 @@
#define NDEBUG #define NDEBUG
#include <kernel32/kernel32.h> #include <kernel32/kernel32.h>
#include <kernel32/error.h>
#define FILE_RENAME_SIZE MAX_PATH +sizeof(FILE_RENAME_INFORMATION) #define FILE_RENAME_SIZE MAX_PATH +sizeof(FILE_RENAME_INFORMATION)
@ -44,6 +45,24 @@ MoveFileExA (
LPCSTR lpNewFileName, LPCSTR lpNewFileName,
DWORD dwFlags 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 ExistingFileNameU;
UNICODE_STRING NewFileNameU; UNICODE_STRING NewFileNameU;
@ -77,8 +96,10 @@ MoveFileExA (
TRUE); TRUE);
} }
Result = MoveFileExW (ExistingFileNameU.Buffer, Result = MoveFileWithProgressW (ExistingFileNameU.Buffer,
NewFileNameU.Buffer, NewFileNameU.Buffer,
lpProgressRoutine,
lpData,
dwFlags); dwFlags);
RtlFreeHeap (RtlGetProcessHeap (), RtlFreeHeap (RtlGetProcessHeap (),
@ -112,12 +133,159 @@ MoveFileExW (
LPCWSTR lpNewFileName, LPCWSTR lpNewFileName,
DWORD dwFlags 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; HANDLE hFile = NULL;
IO_STATUS_BLOCK IoStatusBlock; IO_STATUS_BLOCK IoStatusBlock;
FILE_RENAME_INFORMATION *FileRename; FILE_RENAME_INFORMATION *FileRename;
USHORT Buffer[FILE_RENAME_SIZE]; USHORT Buffer[FILE_RENAME_SIZE];
NTSTATUS errCode; NTSTATUS errCode;
DWORD err;
WINBOOL Result;
hFile = CreateFileW (lpExistingFileName, hFile = CreateFileW (lpExistingFileName,
GENERIC_ALL, GENERIC_ALL,
@ -144,14 +312,56 @@ MoveFileExW (
FILE_RENAME_SIZE, FILE_RENAME_SIZE,
FileRenameInformation); FileRenameInformation);
CloseHandle(hFile); CloseHandle(hFile);
if (!NT_SUCCESS(errCode)) if (NT_SUCCESS(errCode))
{ {
if (CopyFileW (lpExistingFileName, Result = TRUE;
lpNewFileName,
FileRename->Replace))
DeleteFileW (lpExistingFileName);
} }
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 */ /* EOF */

View file

@ -449,8 +449,10 @@ MapViewOfFile@20
MapViewOfFileEx@24 MapViewOfFileEx@24
MoveFileA@8 MoveFileA@8
MoveFileExA@12 MoveFileExA@12
MoveFileWithProgressA@20
MoveFileExW@12 MoveFileExW@12
MoveFileW@8 MoveFileW@8
MoveFileWithProgressW@20
MulDiv@12 MulDiv@12
MultiByteToWideChar@24 MultiByteToWideChar@24
OpenConsoleW@16 OpenConsoleW@16

View file

@ -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 ; kernel32.edf
; ;
@ -453,8 +453,10 @@ MapViewOfFile=MapViewOfFile@20
MapViewOfFileEx=MapViewOfFileEx@24 MapViewOfFileEx=MapViewOfFileEx@24
MoveFileA=MoveFileA@8 MoveFileA=MoveFileA@8
MoveFileExA=MoveFileExA@12 MoveFileExA=MoveFileExA@12
MoveFileWithProgressA=MoveFileWithProgressA@20
MoveFileExW=MoveFileExW@12 MoveFileExW=MoveFileExW@12
MoveFileW=MoveFileW@8 MoveFileW=MoveFileW@8
MoveFileWithProgressW=MoveFileWithProgressW@20
MulDiv=MulDiv@12 MulDiv=MulDiv@12
MultiByteToWideChar=MultiByteToWideChar@24 MultiByteToWideChar=MultiByteToWideChar@24
OpenConsoleW=OpenConsoleW@16 OpenConsoleW=OpenConsoleW@16