/* INCLUDES *****************************************************************/
#include <k32.h>
+#include <wine/debug.h>
-#define NDEBUG
-#include "../include/debug.h"
-
+WINE_DEFAULT_DEBUG_CHANNEL(kernel32file);
/* GLOBALS ******************************************************************/
PUNICODE_STRING pstrW;
NTSTATUS Status;
- ASSERT(NtCurrentTeb()->StaticUnicodeString.Buffer == NtCurrentTeb()->StaticUnicodeBuffer);
+ //ASSERT(NtCurrentTeb()->StaticUnicodeString.Buffer == NtCurrentTeb()->StaticUnicodeBuffer);
ASSERT(NtCurrentTeb()->StaticUnicodeString.MaximumLength == sizeof(NtCurrentTeb()->StaticUnicodeBuffer));
RtlInitAnsiString(&str, NameA);
pstrW = alloc ? &strW : &NtCurrentTeb()->StaticUnicodeString;
if (bIsFileApiAnsi)
- Status= RtlAnsiStringToUnicodeString( pstrW, &str, alloc );
+ Status= RtlAnsiStringToUnicodeString( pstrW, &str, (BOOLEAN)alloc );
else
- Status= RtlOemStringToUnicodeString( pstrW, &str, alloc );
+ Status= RtlOemStringToUnicodeString( pstrW, &str, (BOOLEAN)alloc );
if (NT_SUCCESS(Status))
return pstrW->Buffer;
ANSI_STRING str;
str.Buffer = DestA;
- str.MaximumLength = destLen;
+ str.MaximumLength = (USHORT)destLen;
if (bIsFileApiAnsi)
* @implemented
*/
VOID
-STDCALL
+WINAPI
SetFileApisToOEM(VOID)
{
/* Set the correct Base Api */
* @implemented
*/
VOID
-STDCALL
+WINAPI
SetFileApisToANSI(VOID)
{
/* Set the correct Base Api */
/*
* @implemented
*/
-BOOL STDCALL
+BOOL WINAPI
AreFileApisANSI(VOID)
{
return bIsFileApiAnsi;
/*
* @implemented
*/
-HFILE STDCALL
+HFILE WINAPI
OpenFile(LPCSTR lpFileName,
LPOFSTRUCT lpReOpenBuff,
UINT uStyle)
PWCHAR FilePart;
ULONG Len;
- DPRINT("OpenFile('%s', lpReOpenBuff %x, uStyle %x)\n", lpFileName, lpReOpenBuff, uStyle);
+ TRACE("OpenFile('%s', lpReOpenBuff %x, uStyle %x)\n", lpFileName, lpReOpenBuff, uStyle);
if (lpReOpenBuff == NULL)
{
- return FALSE;
+ return HFILE_ERROR;
+ }
+
+ lpReOpenBuff->nErrCode = 0;
+
+ if (uStyle & OF_REOPEN) lpFileName = lpReOpenBuff->szPathName;
+
+ if (!lpFileName)
+ {
+ return HFILE_ERROR;
+ }
+
+ if (!GetFullPathNameA(lpFileName,
+ sizeof(lpReOpenBuff->szPathName),
+ lpReOpenBuff->szPathName,
+ NULL))
+ {
+ lpReOpenBuff->nErrCode = GetLastError();
+ return HFILE_ERROR;
}
+ if (uStyle & OF_PARSE)
+ {
+ lpReOpenBuff->fFixedDisk = (GetDriveTypeA(lpReOpenBuff->szPathName) != DRIVE_REMOVABLE);
+ TRACE("(%s): OF_PARSE, res = '%s'\n", lpFileName, lpReOpenBuff->szPathName);
+ return 0;
+ }
+
+ if ((uStyle & OF_EXIST) && !(uStyle & OF_CREATE))
+ {
+ DWORD dwAttributes = GetFileAttributesA(lpReOpenBuff->szPathName);
+
+ switch (dwAttributes)
+ {
+ case 0xFFFFFFFF: /* File does not exist */
+ SetLastError(ERROR_FILE_NOT_FOUND);
+ lpReOpenBuff->nErrCode = (WORD) ERROR_FILE_NOT_FOUND;
+ return -1;
+
+ case FILE_ATTRIBUTE_DIRECTORY:
+ SetLastError(ERROR_ACCESS_DENIED);
+ lpReOpenBuff->nErrCode = (WORD) ERROR_ACCESS_DENIED;
+ return -1;
+
+ default:
+ lpReOpenBuff->cBytes = sizeof(OFSTRUCT);
+ return 1;
+ }
+ }
+ lpReOpenBuff->cBytes = sizeof(OFSTRUCT);
if ((uStyle & OF_CREATE) == OF_CREATE)
{
DWORD Sharing;
if (Len == 0 || Len > OFS_MAXPATHNAME)
{
+ lpReOpenBuff->nErrCode = GetLastError();
return (HFILE)INVALID_HANDLE_VALUE;
}
+ if (uStyle & OF_DELETE)
+ {
+ if (!DeleteFileW(PathNameW))
+ {
+ lpReOpenBuff->nErrCode = GetLastError();
+ return HFILE_ERROR;
+ }
+ TRACE("(%s): OF_DELETE return = OK\n", lpFileName);
+ return TRUE;
+ }
+
FileName.Buffer = lpReOpenBuff->szPathName;
FileName.Length = 0;
FileName.MaximumLength = OFS_MAXPATHNAME;
// FILE_SHARE_READ
// FILE_NO_INTERMEDIATE_BUFFERING
- if ((uStyle & OF_PARSE) == OF_PARSE)
- {
- RtlFreeHeap(RtlGetProcessHeap(),
- 0,
- FileNameString.Buffer);
- return (HFILE)NULL;
- }
-
ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
ObjectAttributes.RootDirectory = NULL;
ObjectAttributes.ObjectName = &FileNameString;
FILE_SHARE_READ,
FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT);
- RtlFreeHeap(RtlGetProcessHeap(),
- 0,
- FileNameString.Buffer);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameString.Buffer);
lpReOpenBuff->nErrCode = RtlNtStatusToDosError(errCode);
return (HFILE)INVALID_HANDLE_VALUE;
}
+ if (uStyle & OF_EXIST)
+ {
+ NtClose(FileHandle);
+ return (HFILE)1;
+ }
+
return (HFILE)FileHandle;
}
/*
* @implemented
*/
-BOOL STDCALL
+BOOL WINAPI
FlushFileBuffers(HANDLE hFile)
{
NTSTATUS errCode;
IO_STATUS_BLOCK IoStatusBlock;
+ hFile = TranslateStdHandle(hFile);
+
if (IsConsoleHandle(hFile))
{
return FALSE;
/*
* @implemented
*/
-DWORD STDCALL
+DWORD WINAPI
SetFilePointer(HANDLE hFile,
- LONG lDistanceToMove,
- PLONG lpDistanceToMoveHigh,
- DWORD dwMoveMethod)
+ LONG lDistanceToMove,
+ PLONG lpDistanceToMoveHigh,
+ DWORD dwMoveMethod)
{
FILE_POSITION_INFORMATION FilePosition;
FILE_STANDARD_INFORMATION FileStandard;
IO_STATUS_BLOCK IoStatusBlock;
LARGE_INTEGER Distance;
- DPRINT("SetFilePointer(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n",
- hFile,lDistanceToMove,dwMoveMethod);
+ TRACE("SetFilePointer(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n",
+ hFile,lDistanceToMove,dwMoveMethod);
if(IsConsoleHandle(hFile))
{
SetLastError(ERROR_INVALID_HANDLE);
- return -1;
+ return INVALID_SET_FILE_POINTER;
}
- Distance.u.LowPart = lDistanceToMove;
if (lpDistanceToMoveHigh)
{
Distance.u.HighPart = *lpDistanceToMoveHigh;
- }
- else if (lDistanceToMove >= 0)
- {
- Distance.u.HighPart = 0;
+ Distance.u.LowPart = lDistanceToMove;
}
else
{
- Distance.u.HighPart = -1;
+ Distance.QuadPart = lDistanceToMove;
}
switch(dwMoveMethod)
{
case FILE_CURRENT:
- NtQueryInformationFile(hFile,
- &IoStatusBlock,
- &FilePosition,
- sizeof(FILE_POSITION_INFORMATION),
- FilePositionInformation);
- FilePosition.CurrentByteOffset.QuadPart += Distance.QuadPart;
- break;
+ errCode = NtQueryInformationFile(hFile,
+ &IoStatusBlock,
+ &FilePosition,
+ sizeof(FILE_POSITION_INFORMATION),
+ FilePositionInformation);
+ FilePosition.CurrentByteOffset.QuadPart += Distance.QuadPart;
+ if (!NT_SUCCESS(errCode))
+ {
+ if (lpDistanceToMoveHigh != NULL)
+ *lpDistanceToMoveHigh = -1;
+ SetLastErrorByStatus(errCode);
+ return INVALID_SET_FILE_POINTER;
+ }
+ break;
case FILE_END:
- NtQueryInformationFile(hFile,
+ errCode = NtQueryInformationFile(hFile,
&IoStatusBlock,
&FileStandard,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation);
- FilePosition.CurrentByteOffset.QuadPart =
+ FilePosition.CurrentByteOffset.QuadPart =
FileStandard.EndOfFile.QuadPart + Distance.QuadPart;
- break;
+ if (!NT_SUCCESS(errCode))
+ {
+ if (lpDistanceToMoveHigh != NULL)
+ *lpDistanceToMoveHigh = -1;
+ SetLastErrorByStatus(errCode);
+ return INVALID_SET_FILE_POINTER;
+ }
+ break;
case FILE_BEGIN:
FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart;
- break;
+ break;
default:
SetLastError(ERROR_INVALID_PARAMETER);
- return -1;
+ return INVALID_SET_FILE_POINTER;
}
if(FilePosition.CurrentByteOffset.QuadPart < 0)
{
SetLastError(ERROR_NEGATIVE_SEEK);
- return -1;
+ return INVALID_SET_FILE_POINTER;
+ }
+
+ if (lpDistanceToMoveHigh == NULL && FilePosition.CurrentByteOffset.HighPart != 0)
+ {
+ /* If we're moving the pointer outside of the 32 bit boundaries but
+ the application only passed a 32 bit value we need to bail out! */
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return INVALID_SET_FILE_POINTER;
}
errCode = NtSetInformationFile(hFile,
- &IoStatusBlock,
- &FilePosition,
- sizeof(FILE_POSITION_INFORMATION),
- FilePositionInformation);
+ &IoStatusBlock,
+ &FilePosition,
+ sizeof(FILE_POSITION_INFORMATION),
+ FilePositionInformation);
if (!NT_SUCCESS(errCode))
{
- SetLastErrorByStatus(errCode);
- return -1;
+ if (lpDistanceToMoveHigh != NULL)
+ *lpDistanceToMoveHigh = -1;
+
+ SetLastErrorByStatus(errCode);
+ return INVALID_SET_FILE_POINTER;
}
if (lpDistanceToMoveHigh != NULL)
{
*lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart;
}
+
+ if (FilePosition.CurrentByteOffset.u.LowPart == MAXDWORD)
+ {
+ /* The value of -1 is valid here, especially when the new
+ file position is greater than 4 GB. Since NtSetInformationFile
+ succeeded we never set an error code and we explicitly need
+ to clear a previously set error code in this case, which
+ an application will check if INVALID_SET_FILE_POINTER is returned! */
+ SetLastError(ERROR_SUCCESS);
+ }
+
return FilePosition.CurrentByteOffset.u.LowPart;
}
* @implemented
*/
BOOL
-STDCALL
+WINAPI
SetFilePointerEx(HANDLE hFile,
LARGE_INTEGER liDistanceToMove,
PLARGE_INTEGER lpNewFilePointer,
/*
* @implemented
*/
-DWORD STDCALL
+DWORD WINAPI
GetFileType(HANDLE hFile)
{
FILE_FS_DEVICE_INFORMATION DeviceInfo;
NTSTATUS Status;
/* Get real handle */
- switch ((ULONG)hFile)
- {
- case STD_INPUT_HANDLE:
- hFile = NtCurrentPeb()->ProcessParameters->StandardInput;
- break;
-
- case STD_OUTPUT_HANDLE:
- hFile = NtCurrentPeb()->ProcessParameters->StandardOutput;
- break;
-
- case STD_ERROR_HANDLE:
- hFile = NtCurrentPeb()->ProcessParameters->StandardError;
- break;
- }
+ hFile = TranslateStdHandle(hFile);
/* Check for console handle */
if (IsConsoleHandle(hFile))
/*
* @implemented
*/
-DWORD STDCALL
+DWORD WINAPI
GetFileSize(HANDLE hFile,
LPDWORD lpFileSizeHigh)
{
* @implemented
*/
BOOL
-STDCALL
+WINAPI
GetFileSizeEx(
HANDLE hFile,
PLARGE_INTEGER lpFileSize
/*
* @implemented
*/
-DWORD STDCALL
+DWORD WINAPI
GetCompressedFileSizeA(LPCSTR lpFileName,
LPDWORD lpFileSizeHigh)
{
/*
* @implemented
*/
-DWORD STDCALL
+DWORD WINAPI
GetCompressedFileSizeW(LPCWSTR lpFileName,
LPDWORD lpFileSizeHigh)
{
/*
* @implemented
*/
-BOOL STDCALL
+BOOL WINAPI
GetFileInformationByHandle(HANDLE hFile,
LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
{
/*
* @implemented
*/
-BOOL STDCALL
+BOOL WINAPI
GetFileAttributesExW(LPCWSTR lpFileName,
GET_FILEEX_INFO_LEVELS fInfoLevelId,
LPVOID lpFileInformation)
NTSTATUS Status;
WIN32_FILE_ATTRIBUTE_DATA* FileAttributeData;
- DPRINT("GetFileAttributesExW(%S) called\n", lpFileName);
+ TRACE("GetFileAttributesExW(%S) called\n", lpFileName);
if (fInfoLevelId != GetFileExInfoStandard || lpFileInformation == NULL)
NULL,
NULL))
{
- DPRINT1 ("Invalid path\n");
+ WARN ("Invalid path '%S'\n", lpFileName);
SetLastError (ERROR_BAD_PATHNAME);
return FALSE;
}
/* Get file attributes */
Status = NtQueryFullAttributesFile(&ObjectAttributes,
&FileInformation);
-
+
RtlFreeUnicodeString (&FileName);
if (!NT_SUCCESS (Status))
{
- DPRINT ("NtQueryFullAttributesFile() failed (Status %lx)\n", Status);
+ WARN ("NtQueryFullAttributesFile() failed (Status %lx)\n", Status);
SetLastErrorByStatus (Status);
return FALSE;
}
/*
* @implemented
*/
-BOOL STDCALL
+BOOL WINAPI
GetFileAttributesExA(LPCSTR lpFileName,
GET_FILEEX_INFO_LEVELS fInfoLevelId,
LPVOID lpFileInformation)
/*
* @implemented
*/
-DWORD STDCALL
+DWORD WINAPI
GetFileAttributesA(LPCSTR lpFileName)
{
WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
PWSTR FileNameW;
- BOOL ret;
+ BOOL ret;
- if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
+ if (!lpFileName || !(FileNameW = FilenameA2W(lpFileName, FALSE)))
return INVALID_FILE_ATTRIBUTES;
ret = GetFileAttributesExW(FileNameW, GetFileExInfoStandard, &FileAttributeData);
/*
* @implemented
*/
-DWORD STDCALL
+DWORD WINAPI
GetFileAttributesW(LPCWSTR lpFileName)
{
WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
BOOL Result;
- DPRINT ("GetFileAttributeW(%S) called\n", lpFileName);
+ TRACE ("GetFileAttributeW(%S) called\n", lpFileName);
Result = GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &FileAttributeData);
/*
* @implemented
*/
-BOOL STDCALL
+BOOL WINAPI
GetFileAttributesByHandle(IN HANDLE hFile,
OUT LPDWORD dwFileAttributes,
IN DWORD dwFlags)
FILE_BASIC_INFORMATION FileBasic;
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status;
-
+
UNREFERENCED_PARAMETER(dwFlags);
-
+
if (IsConsoleHandle(hFile))
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
-
+
Status = NtQueryInformationFile(hFile,
&IoStatusBlock,
&FileBasic,
*dwFileAttributes = FileBasic.FileAttributes;
return TRUE;
}
-
+
SetLastErrorByStatus(Status);
return FALSE;
}
/*
* @implemented
*/
-BOOL STDCALL
+BOOL WINAPI
SetFileAttributesByHandle(IN HANDLE hFile,
IN DWORD dwFileAttributes,
IN DWORD dwFlags)
NTSTATUS Status;
UNREFERENCED_PARAMETER(dwFlags);
-
+
if (IsConsoleHandle(hFile))
{
SetLastError(ERROR_INVALID_HANDLE);
if (NT_SUCCESS(Status))
{
FileBasic.FileAttributes = dwFileAttributes;
-
+
Status = NtSetInformationFile(hFile,
&IoStatusBlock,
&FileBasic,
SetLastErrorByStatus(Status);
return FALSE;
}
-
+
return TRUE;
}
/*
* @implemented
*/
-BOOL STDCALL
+BOOL WINAPI
SetFileAttributesA(
LPCSTR lpFileName,
DWORD dwFileAttributes)
/*
* @implemented
*/
-BOOL STDCALL
+BOOL WINAPI
SetFileAttributesW(LPCWSTR lpFileName,
DWORD dwFileAttributes)
{
HANDLE FileHandle;
NTSTATUS Status;
- DPRINT ("SetFileAttributeW(%S, 0x%lx) called\n", lpFileName, dwFileAttributes);
+ TRACE ("SetFileAttributeW(%S, 0x%lx) called\n", lpFileName, dwFileAttributes);
/* Validate and translate the filename */
if (!RtlDosPathNameToNtPathName_U (lpFileName,
NULL,
NULL))
{
- DPRINT ("Invalid path\n");
+ WARN ("Invalid path\n");
SetLastError (ERROR_BAD_PATHNAME);
return FALSE;
}
- DPRINT ("FileName: \'%wZ\'\n", &FileName);
+ TRACE ("FileName: \'%wZ\'\n", &FileName);
/* build the object attributes */
InitializeObjectAttributes (&ObjectAttributes,
RtlFreeUnicodeString (&FileName);
if (!NT_SUCCESS (Status))
{
- DPRINT ("NtOpenFile() failed (Status %lx)\n", Status);
+ WARN ("NtOpenFile() failed (Status %lx)\n", Status);
SetLastErrorByStatus (Status);
return FALSE;
}
FileBasicInformation);
if (!NT_SUCCESS(Status))
{
- DPRINT ("SetFileAttributes NtQueryInformationFile failed with status 0x%08x\n", Status);
+ WARN ("SetFileAttributes NtQueryInformationFile failed with status 0x%08x\n", Status);
NtClose (FileHandle);
SetLastErrorByStatus (Status);
return FALSE;
NtClose (FileHandle);
if (!NT_SUCCESS(Status))
{
- DPRINT ("SetFileAttributes NtSetInformationFile failed with status 0x%08x\n", Status);
+ WARN ("SetFileAttributes NtSetInformationFile failed with status 0x%08x\n", Status);
SetLastErrorByStatus (Status);
return FALSE;
}
int i;
LPWSTR p;
- if ( !path || !prefix || !buffer )
+ if ( !path || !buffer )
{
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
/* add a \, if there isn't one */
if ((p == buffer) || (p[-1] != '\\')) *p++ = '\\';
- for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++;
+ if ( prefix )
+ for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++;
unique &= 0xffff;
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
if (handle != INVALID_HANDLE_VALUE)
{ /* We created it */
- DPRINT("created %S\n", buffer);
+ TRACE("created %S\n", buffer);
CloseHandle( handle );
break;
}
} while (unique != num);
}
- DPRINT("returning %S\n", buffer);
+ TRACE("returning %S\n", buffer);
return unique;
}
/*
* @implemented
*/
-BOOL STDCALL
+BOOL WINAPI
GetFileTime(HANDLE hFile,
LPFILETIME lpCreationTime,
LPFILETIME lpLastAccessTime,
/*
* @implemented
*/
-BOOL STDCALL
+BOOL WINAPI
SetFileTime(HANDLE hFile,
CONST FILETIME *lpCreationTime,
CONST FILETIME *lpLastAccessTime,
*
* @implemented
*/
-BOOL STDCALL
+BOOL WINAPI
SetEndOfFile(HANDLE hFile)
{
IO_STATUS_BLOCK IoStatusBlock;
* @implemented
*/
BOOL
-STDCALL
+WINAPI
SetFileValidData(
HANDLE hFile,
LONGLONG ValidDataLength
* @implemented
*/
BOOL
-STDCALL
+WINAPI
SetFileShortNameW(
HANDLE hFile,
LPCWSTR lpShortName)
* @implemented
*/
BOOL
-STDCALL
+WINAPI
SetFileShortNameA(
HANDLE hFile,
LPCSTR lpShortName
* @implemented
*/
BOOL
-STDCALL
+WINAPI
CheckNameLegalDOS8Dot3W(
LPCWSTR lpName,
LPSTR lpOemName OPTIONAL,
if(lpOemName != NULL)
{
AnsiName.Buffer = lpOemName;
- AnsiName.MaximumLength = OemNameSize * sizeof(CHAR);
+ AnsiName.MaximumLength = (USHORT)OemNameSize * sizeof(CHAR);
AnsiName.Length = 0;
}
* @implemented
*/
BOOL
-STDCALL
+WINAPI
CheckNameLegalDOS8Dot3A(
LPCSTR lpName,
LPSTR lpOemName OPTIONAL,
if(lpOemName != NULL)
{
AnsiName.Buffer = lpOemName;
- AnsiName.MaximumLength = OemNameSize * sizeof(CHAR);
+ AnsiName.MaximumLength = (USHORT)OemNameSize * sizeof(CHAR);
AnsiName.Length = 0;
}
cchFilePath > sizeof(FilePathW) / sizeof(FilePathW[0]))
{
FilePathU.Length = 0;
- FilePathU.MaximumLength = cchFilePath * sizeof(WCHAR);
+ FilePathU.MaximumLength = (USHORT)cchFilePath * sizeof(WCHAR);
FilePathU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
0,
FilePathU.MaximumLength);
return INVALID_HANDLE_VALUE;
}
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+ReplaceFileA(
+ LPCSTR lpReplacedFileName,
+ LPCSTR lpReplacementFileName,
+ LPCSTR lpBackupFileName,
+ DWORD dwReplaceFlags,
+ LPVOID lpExclude,
+ LPVOID lpReserved
+ )
+{
+ WCHAR *replacedW, *replacementW, *backupW = NULL;
+ BOOL ret;
+
+ /* This function only makes sense when the first two parameters are defined */
+ if (!lpReplacedFileName || !(replacedW = FilenameA2W(lpReplacedFileName, TRUE)))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ if (!lpReplacementFileName || !(replacementW = FilenameA2W(lpReplacementFileName, TRUE)))
+ {
+ HeapFree(GetProcessHeap(), 0, replacedW);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ /* The backup parameter, however, is optional */
+ if (lpBackupFileName)
+ {
+ if (!(backupW = FilenameA2W(lpBackupFileName, TRUE)))
+ {
+ HeapFree(GetProcessHeap(), 0, replacedW);
+ HeapFree(GetProcessHeap(), 0, replacementW);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ }
+
+ ret = ReplaceFileW(replacedW, replacementW, backupW, dwReplaceFlags, lpExclude, lpReserved);
+ HeapFree(GetProcessHeap(), 0, replacedW);
+ HeapFree(GetProcessHeap(), 0, replacementW);
+ HeapFree(GetProcessHeap(), 0, backupW);
+
+ return ret;
+}
+
+/*
+ * @unimplemented
+ */
+BOOL
+WINAPI
+ReplaceFileW(
+ LPCWSTR lpReplacedFileName,
+ LPCWSTR lpReplacementFileName,
+ LPCWSTR lpBackupFileName,
+ DWORD dwReplaceFlags,
+ LPVOID lpExclude,
+ LPVOID lpReserved
+ )
+{
+ HANDLE hReplaced = NULL, hReplacement = NULL;
+ UNICODE_STRING NtReplacedName = { 0, 0, NULL };
+ UNICODE_STRING NtReplacementName = { 0, 0, NULL };
+ DWORD Error = ERROR_SUCCESS;
+ NTSTATUS Status;
+ BOOL Ret = FALSE;
+ IO_STATUS_BLOCK IoStatusBlock;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PVOID Buffer = NULL ;
+
+ if (dwReplaceFlags)
+ FIXME("Ignoring flags %x\n", dwReplaceFlags);
+
+ /* First two arguments are mandatory */
+ if (!lpReplacedFileName || !lpReplacementFileName)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ /* Back it up */
+ if(lpBackupFileName)
+ {
+ if(!CopyFileW(lpReplacedFileName, lpBackupFileName, FALSE))
+ {
+ Error = GetLastError();
+ goto Cleanup ;
+ }
+ }
+
+ /* Open the "replaced" file for reading and writing */
+ if (!(RtlDosPathNameToNtPathName_U(lpReplacedFileName, &NtReplacedName, NULL, NULL)))
+ {
+ Error = ERROR_PATH_NOT_FOUND;
+ goto Cleanup;
+ }
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &NtReplacedName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&hReplaced,
+ GENERIC_READ | GENERIC_WRITE | DELETE | SYNCHRONIZE | WRITE_DAC,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
+
+ if (!NT_SUCCESS(Status))
+ {
+ if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+ Error = ERROR_FILE_NOT_FOUND;
+ else
+ Error = ERROR_UNABLE_TO_REMOVE_REPLACED;
+ goto Cleanup;
+ }
+
+ /* Blank it */
+ SetEndOfFile(hReplaced) ;
+
+ /*
+ * Open the replacement file for reading, writing, and deleting
+ * (deleting is needed when finished)
+ */
+ if (!(RtlDosPathNameToNtPathName_U(lpReplacementFileName, &NtReplacementName, NULL, NULL)))
+ {
+ Error = ERROR_PATH_NOT_FOUND;
+ goto Cleanup;
+ }
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &NtReplacementName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&hReplacement,
+ GENERIC_READ | DELETE | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE);
+
+ if (!NT_SUCCESS(Status))
+ {
+ Error = RtlNtStatusToDosError(Status);
+ goto Cleanup;
+ }
+
+ Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 0x10000) ;
+ if (!Buffer)
+ {
+ Error = ERROR_NOT_ENOUGH_MEMORY;
+ goto Cleanup ;
+ }
+ while (Status != STATUS_END_OF_FILE)
+ {
+ Status = NtReadFile(hReplacement, NULL, NULL, NULL, &IoStatusBlock, Buffer, 0x10000, NULL, NULL) ;
+ if (NT_SUCCESS(Status))
+ {
+ Status = NtWriteFile(hReplaced, NULL, NULL, NULL, &IoStatusBlock, Buffer,
+ IoStatusBlock.Information, NULL, NULL) ;
+ if (!NT_SUCCESS(Status))
+ {
+ Error = RtlNtStatusToDosError(Status);
+ goto Cleanup;
+ }
+ }
+ else if (Status != STATUS_END_OF_FILE)
+ {
+ Error = RtlNtStatusToDosError(Status);
+ goto Cleanup;
+ }
+ }
+
+ Ret = TRUE;
+
+ /* Perform resource cleanup */
+Cleanup:
+ if (hReplaced) NtClose(hReplaced);
+ if (hReplacement) NtClose(hReplacement);
+ if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
+
+ if (NtReplacementName.Buffer)
+ RtlFreeHeap(GetProcessHeap(), 0, NtReplacementName.Buffer);
+ if (NtReplacedName.Buffer)
+ RtlFreeHeap(GetProcessHeap(), 0, NtReplacedName.Buffer);
+
+ /* If there was an error, set the error code */
+ if(!Ret)
+ {
+ TRACE("ReplaceFileW failed (error=%d)\n", Error);
+ SetLastError(Error);
+ }
+ return Ret;
+}
+
/* EOF */