2005-01-06 13:58:04 +00:00
|
|
|
/* $Id$
|
2000-06-03 14:47:33 +00:00
|
|
|
*
|
1998-12-04 18:28:13 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS system libraries
|
|
|
|
* FILE: lib/kernel32/file/file.c
|
|
|
|
* PURPOSE: Directory functions
|
|
|
|
* PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
|
1999-02-07 00:37:29 +00:00
|
|
|
* GetTempFileName is modified from WINE [ Alexandre Juiliard ]
|
1998-12-04 18:28:13 +00:00
|
|
|
* UPDATE HISTORY:
|
|
|
|
* Created 01/11/98
|
1996-01-23 01:02:17 +00:00
|
|
|
*/
|
|
|
|
|
1999-05-19 17:57:02 +00:00
|
|
|
/* INCLUDES *****************************************************************/
|
1999-03-19 05:55:55 +00:00
|
|
|
|
2003-01-15 21:24:36 +00:00
|
|
|
#include <k32.h>
|
[KERNEL32]: While working on the CMAKE branch, Amine and myself discovered a rather serious issue in kernel32 (and perhaps other libraries as well). Unlike rbuild, CMake does not allow you to export non-existant DLL functions (try it: add "poopyhead" in kernel32's exports under RBuild, and will it export "poopyhead", God knowing what that will actually link to).
As an additional feature on top of the "allow non-existing functions to be exported" "feature", because rbuild generates and links STDCALL function names without the proper decoration (vs. enforcing decoration at linking, but only removing it at export-time), this allows the definition (as an export) of a STDCALL function that is completely different from the actual function itself.
For example, the 5-parameter Foo function is normally Foo@20, while the 3-parameter Foo function woudl be Foo@12. Linking one against the other would fail (say, 2 parameters were added to Foo in a newer version). However, under RBUILD, both of these would appear as "Foo", and the linker/compiler would happilly connect the caller of Foo@3 (that has pushed 3 parameters) to the receiving side of Foo@5 (that is about to pop 5 parameters).
Even -if- decorations WERE to be applied, Foo@12 would STILL succeed, because of the first feature, which would enable the export of Foo@12 even though no such function exist.
In a further, bizare, twist of fate, the behavior of this RBUILD "feature", when the target function is not found, is to link the exported DLL TO ITSELF.
Therefore, one can see how, previously to this patch, kernel32.dll would import a dozen functions from itself (all the non-existing functions).
To really seal the deal, the behavior of exported functions used by kernel32, but that are actually forwarded to another DLL deserves a special mention.
GetLastError, for example, merely forwards to RtlGetLastWin32Error, so it is normal behavior to use a #define in the C code so that all internal calls to the function are routed correctly.
This did not happen, so instead, kernel32 tried importing/linking/exporting GetLastError, but this symbol is not found in the binary, because it is only a forwarder.
This caused kernel32 to import from itself (the behavior when an exported symbol is not found). When importing from itself, the loader would now find the _forwarded_ for GetLastError, and correctly link with ntdll.
What should be a one-liner of assembly (inline TEB access) thus became a triple-call indirection (GetLastError@0->StubLastError@0->__impGetLastError@0->__impRtlGetLastWin32Error->RtlGetLastWin32Error.
While analyzing these issues, we also realized a strange macro SetLastErrorByStatus that manually tried to perform what there already exists a function for: RtlSetLastNtStatusFromWin32Error.
And, in an exciting coda, we also realized that our Server 2003 Kernel32 exports more than a dozen Windows 95 APIs, through an auto-stub generation mechanism within winebuild, that gets linked as an object behind the scenes.
[KERNEL32]: Removed all Win95 exports, cleaned up exports.
[KERNEL32]: Fixed up set/get error macros by making them inline and/or calling the correct ntdll function.
[KERNEL32]: Removed bizare calls to Wine-internal/specific APIs from our core Win32 DLL.
[KERNEL32]: Wrote stubs for all functions which should be exported, and set the correct number of parameters for them.
[KERNEL32]: Kernel32 is smaller, loads faster, does not export Windows 95 functions, does not export non-existing functions, and does not import from itself anymore.
Note: This is one of the many failings of RBUILD the CMAKE system has helped us discover. I believe these issues are serious enough to warrant an immediate sync with trunk, but rest assured, there are many more completely broken, infinitely-regressing things that we discovered while switching to CMAKE.
svn path=/trunk/; revision=48475
2010-08-07 05:02:58 +00:00
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
2010-09-21 17:14:22 +00:00
|
|
|
DEBUG_CHANNEL(kernel32file);
|
2000-02-18 00:51:03 +00:00
|
|
|
|
1999-03-19 05:55:55 +00:00
|
|
|
/* GLOBALS ******************************************************************/
|
1998-12-04 18:28:13 +00:00
|
|
|
|
2004-01-23 16:37:11 +00:00
|
|
|
BOOL bIsFileApiAnsi = TRUE; // set the file api to ansi or oem
|
2000-02-18 00:51:03 +00:00
|
|
|
|
1999-03-19 05:55:55 +00:00
|
|
|
/* FUNCTIONS ****************************************************************/
|
1998-12-04 18:28:13 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
|
|
|
|
|
2005-03-20 17:26:58 +00:00
|
|
|
PWCHAR
|
|
|
|
FilenameA2W(LPCSTR NameA, BOOL alloc)
|
2005-03-15 19:40:22 +00:00
|
|
|
{
|
|
|
|
ANSI_STRING str;
|
|
|
|
UNICODE_STRING strW;
|
|
|
|
PUNICODE_STRING pstrW;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
2007-01-26 07:22:19 +00:00
|
|
|
//ASSERT(NtCurrentTeb()->StaticUnicodeString.Buffer == NtCurrentTeb()->StaticUnicodeBuffer);
|
2005-03-15 19:40:22 +00:00
|
|
|
ASSERT(NtCurrentTeb()->StaticUnicodeString.MaximumLength == sizeof(NtCurrentTeb()->StaticUnicodeBuffer));
|
|
|
|
|
|
|
|
RtlInitAnsiString(&str, NameA);
|
|
|
|
pstrW = alloc ? &strW : &NtCurrentTeb()->StaticUnicodeString;
|
|
|
|
|
|
|
|
if (bIsFileApiAnsi)
|
2007-01-26 07:22:19 +00:00
|
|
|
Status= RtlAnsiStringToUnicodeString( pstrW, &str, (BOOLEAN)alloc );
|
2005-03-15 19:40:22 +00:00
|
|
|
else
|
2007-01-26 07:22:19 +00:00
|
|
|
Status= RtlOemStringToUnicodeString( pstrW, &str, (BOOLEAN)alloc );
|
2005-03-15 19:40:22 +00:00
|
|
|
|
|
|
|
if (NT_SUCCESS(Status))
|
2005-03-20 17:26:58 +00:00
|
|
|
return pstrW->Buffer;
|
2005-03-15 19:40:22 +00:00
|
|
|
|
|
|
|
if (Status== STATUS_BUFFER_OVERFLOW)
|
|
|
|
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
|
|
|
else
|
|
|
|
SetLastErrorByStatus(Status);
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
No copy/conversion is done if the dest. buffer is too small.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Success: number of TCHARS copied into dest. buffer NOT including nullterm
|
|
|
|
Fail: size of buffer in TCHARS required to hold the converted filename, including nullterm
|
|
|
|
*/
|
2005-05-09 01:46:57 +00:00
|
|
|
DWORD
|
2005-03-15 19:40:22 +00:00
|
|
|
FilenameU2A_FitOrFail(
|
|
|
|
LPSTR DestA,
|
|
|
|
INT destLen, /* buffer size in TCHARS incl. nullchar */
|
|
|
|
PUNICODE_STRING SourceU
|
|
|
|
)
|
|
|
|
{
|
|
|
|
DWORD ret;
|
|
|
|
|
|
|
|
ret = bIsFileApiAnsi? RtlUnicodeStringToAnsiSize(SourceU) : RtlUnicodeStringToOemSize(SourceU);
|
|
|
|
/* ret incl. nullchar */
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-07-05 22:35:29 +00:00
|
|
|
if (DestA && (INT)ret <= destLen)
|
2005-03-15 19:40:22 +00:00
|
|
|
{
|
|
|
|
ANSI_STRING str;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
str.Buffer = DestA;
|
2007-01-26 07:22:19 +00:00
|
|
|
str.MaximumLength = (USHORT)destLen;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
if (bIsFileApiAnsi)
|
|
|
|
RtlUnicodeStringToAnsiString(&str, SourceU, FALSE );
|
|
|
|
else
|
|
|
|
RtlUnicodeStringToOemString(&str, SourceU, FALSE );
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
ret = str.Length; /* SUCCESS: length without terminating 0 */
|
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
No copy/conversion is done if the dest. buffer is too small.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Success: number of TCHARS copied into dest. buffer NOT including nullterm
|
|
|
|
Fail: size of buffer in TCHARS required to hold the converted filename, including nullterm
|
|
|
|
*/
|
2005-05-09 01:46:57 +00:00
|
|
|
DWORD
|
2005-03-15 19:40:22 +00:00
|
|
|
FilenameW2A_FitOrFail(
|
|
|
|
LPSTR DestA,
|
|
|
|
INT destLen, /* buffer size in TCHARS incl. nullchar */
|
|
|
|
LPCWSTR SourceW,
|
|
|
|
INT sourceLen /* buffer size in TCHARS incl. nullchar */
|
|
|
|
)
|
|
|
|
{
|
|
|
|
UNICODE_STRING strW;
|
|
|
|
|
|
|
|
if (sourceLen < 0) sourceLen = wcslen(SourceW) + 1;
|
|
|
|
|
|
|
|
strW.Buffer = (PWCHAR)SourceW;
|
|
|
|
strW.MaximumLength = sourceLen * sizeof(WCHAR);
|
|
|
|
strW.Length = strW.MaximumLength - sizeof(WCHAR);
|
|
|
|
|
2005-05-09 01:46:57 +00:00
|
|
|
return FilenameU2A_FitOrFail(DestA, destLen, &strW);
|
2005-03-15 19:40:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-03-20 17:26:58 +00:00
|
|
|
/*
|
|
|
|
Return: num. TCHARS copied into dest including nullterm
|
|
|
|
*/
|
2005-05-09 01:46:57 +00:00
|
|
|
DWORD
|
|
|
|
FilenameA2W_N(
|
|
|
|
LPWSTR dest,
|
2005-03-15 19:40:22 +00:00
|
|
|
INT destlen, /* buffer size in TCHARS incl. nullchar */
|
2005-05-09 01:46:57 +00:00
|
|
|
LPCSTR src,
|
2005-03-15 19:40:22 +00:00
|
|
|
INT srclen /* buffer size in TCHARS incl. nullchar */
|
|
|
|
)
|
|
|
|
{
|
|
|
|
DWORD ret;
|
|
|
|
|
|
|
|
if (srclen < 0) srclen = strlen( src ) + 1;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
if (bIsFileApiAnsi)
|
2005-05-09 01:46:57 +00:00
|
|
|
RtlMultiByteToUnicodeN( dest, destlen* sizeof(WCHAR), &ret, (LPSTR)src, srclen );
|
2005-03-15 19:40:22 +00:00
|
|
|
else
|
|
|
|
RtlOemToUnicodeN( dest, destlen* sizeof(WCHAR), &ret, (LPSTR)src, srclen );
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
if (ret) dest[(ret/sizeof(WCHAR))-1]=0;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-03-20 17:26:58 +00:00
|
|
|
return ret/sizeof(WCHAR);
|
2005-03-15 19:40:22 +00:00
|
|
|
}
|
|
|
|
|
2005-03-20 17:26:58 +00:00
|
|
|
/*
|
|
|
|
Return: num. TCHARS copied into dest including nullterm
|
|
|
|
*/
|
2005-05-09 01:46:57 +00:00
|
|
|
DWORD
|
|
|
|
FilenameW2A_N(
|
|
|
|
LPSTR dest,
|
2005-03-15 19:40:22 +00:00
|
|
|
INT destlen, /* buffer size in TCHARS incl. nullchar */
|
2005-05-09 01:46:57 +00:00
|
|
|
LPCWSTR src,
|
2005-03-15 19:40:22 +00:00
|
|
|
INT srclen /* buffer size in TCHARS incl. nullchar */
|
|
|
|
)
|
|
|
|
{
|
|
|
|
DWORD ret;
|
|
|
|
|
|
|
|
if (srclen < 0) srclen = wcslen( src ) + 1;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
if (bIsFileApiAnsi)
|
|
|
|
RtlUnicodeToMultiByteN( dest, destlen, &ret, (LPWSTR) src, srclen * sizeof(WCHAR));
|
|
|
|
else
|
2005-05-09 01:46:57 +00:00
|
|
|
RtlUnicodeToOemN( dest, destlen, &ret, (LPWSTR) src, srclen * sizeof(WCHAR) );
|
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
if (ret) dest[ret-1]=0;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-07-12 05:00:33 +00:00
|
|
|
VOID
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2001-07-19 18:42:02 +00:00
|
|
|
SetFileApisToOEM(VOID)
|
1996-01-23 01:02:17 +00:00
|
|
|
{
|
2005-07-12 05:00:33 +00:00
|
|
|
/* Set the correct Base Api */
|
2005-09-05 18:06:20 +00:00
|
|
|
Basep8BitStringToUnicodeString = (PRTL_CONVERT_STRING)RtlOemStringToUnicodeString;
|
2005-07-12 05:00:33 +00:00
|
|
|
|
|
|
|
/* FIXME: Old, deprecated way */
|
|
|
|
bIsFileApiAnsi = FALSE;
|
1996-01-23 01:02:17 +00:00
|
|
|
}
|
|
|
|
|
1999-05-19 17:57:02 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-07-12 05:00:33 +00:00
|
|
|
VOID
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2001-07-19 18:42:02 +00:00
|
|
|
SetFileApisToANSI(VOID)
|
1996-01-23 01:02:17 +00:00
|
|
|
{
|
2005-07-12 05:00:33 +00:00
|
|
|
/* Set the correct Base Api */
|
|
|
|
Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString;
|
|
|
|
|
|
|
|
/* FIXME: Old, deprecated way */
|
|
|
|
bIsFileApiAnsi = TRUE;
|
1996-01-23 01:02:17 +00:00
|
|
|
}
|
|
|
|
|
1999-05-19 17:57:02 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-30 11:42:05 +00:00
|
|
|
BOOL WINAPI
|
2001-07-19 18:42:02 +00:00
|
|
|
AreFileApisANSI(VOID)
|
1996-01-23 01:02:17 +00:00
|
|
|
{
|
2001-07-19 18:42:02 +00:00
|
|
|
return bIsFileApiAnsi;
|
1996-01-23 01:02:17 +00:00
|
|
|
}
|
1998-10-05 04:01:30 +00:00
|
|
|
|
1999-05-19 17:57:02 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-30 11:42:05 +00:00
|
|
|
HFILE WINAPI
|
2001-07-19 18:42:02 +00:00
|
|
|
OpenFile(LPCSTR lpFileName,
|
|
|
|
LPOFSTRUCT lpReOpenBuff,
|
|
|
|
UINT uStyle)
|
1998-10-05 04:01:30 +00:00
|
|
|
{
|
2000-03-15 18:30:30 +00:00
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
UNICODE_STRING FileNameString;
|
|
|
|
UNICODE_STRING FileNameU;
|
|
|
|
ANSI_STRING FileName;
|
|
|
|
WCHAR PathNameW[MAX_PATH];
|
|
|
|
HANDLE FileHandle = NULL;
|
|
|
|
NTSTATUS errCode;
|
|
|
|
PWCHAR FilePart;
|
|
|
|
ULONG Len;
|
|
|
|
|
2008-05-12 12:01:51 +00:00
|
|
|
TRACE("OpenFile('%s', lpReOpenBuff %x, uStyle %x)\n", lpFileName, lpReOpenBuff, uStyle);
|
2002-04-01 22:06:51 +00:00
|
|
|
|
2000-03-15 18:30:30 +00:00
|
|
|
if (lpReOpenBuff == NULL)
|
|
|
|
{
|
2008-12-27 10:31:53 +00:00
|
|
|
return HFILE_ERROR;
|
2000-03-15 18:30:30 +00:00
|
|
|
}
|
1999-04-14 00:52:19 +00:00
|
|
|
|
2008-12-27 10:31:53 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2009-01-10 12:33:22 +00:00
|
|
|
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:
|
2009-12-03 21:50:52 +00:00
|
|
|
lpReOpenBuff->cBytes = sizeof(OFSTRUCT);
|
2009-01-10 12:33:22 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
2009-12-03 21:50:52 +00:00
|
|
|
lpReOpenBuff->cBytes = sizeof(OFSTRUCT);
|
2004-07-24 01:27:54 +00:00
|
|
|
if ((uStyle & OF_CREATE) == OF_CREATE)
|
|
|
|
{
|
|
|
|
DWORD Sharing;
|
|
|
|
switch (uStyle & 0x70)
|
|
|
|
{
|
|
|
|
case OF_SHARE_EXCLUSIVE: Sharing = 0; break;
|
|
|
|
case OF_SHARE_DENY_WRITE: Sharing = FILE_SHARE_READ; break;
|
|
|
|
case OF_SHARE_DENY_READ: Sharing = FILE_SHARE_WRITE; break;
|
|
|
|
case OF_SHARE_DENY_NONE:
|
|
|
|
case OF_SHARE_COMPAT:
|
|
|
|
default:
|
|
|
|
Sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
|
|
|
}
|
|
|
|
return (HFILE) CreateFileA (lpFileName,
|
|
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
|
|
Sharing,
|
|
|
|
NULL,
|
|
|
|
CREATE_ALWAYS,
|
|
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
|
2002-04-01 22:06:51 +00:00
|
|
|
RtlInitAnsiString (&FileName, (LPSTR)lpFileName);
|
1999-04-14 00:52:19 +00:00
|
|
|
|
2000-03-15 18:30:30 +00:00
|
|
|
/* convert ansi (or oem) string to unicode */
|
|
|
|
if (bIsFileApiAnsi)
|
2002-04-01 22:06:51 +00:00
|
|
|
RtlAnsiStringToUnicodeString (&FileNameU, &FileName, TRUE);
|
2000-03-15 18:30:30 +00:00
|
|
|
else
|
2002-04-01 22:06:51 +00:00
|
|
|
RtlOemStringToUnicodeString (&FileNameU, &FileName, TRUE);
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-07-24 01:27:54 +00:00
|
|
|
Len = SearchPathW (NULL,
|
|
|
|
FileNameU.Buffer,
|
|
|
|
NULL,
|
|
|
|
OFS_MAXPATHNAME,
|
|
|
|
PathNameW,
|
|
|
|
&FilePart);
|
2004-05-25 20:04:14 +00:00
|
|
|
|
2004-07-24 01:27:54 +00:00
|
|
|
RtlFreeUnicodeString(&FileNameU);
|
2004-05-25 20:04:14 +00:00
|
|
|
|
2004-07-24 01:27:54 +00:00
|
|
|
if (Len == 0 || Len > OFS_MAXPATHNAME)
|
|
|
|
{
|
2008-12-27 10:31:53 +00:00
|
|
|
lpReOpenBuff->nErrCode = GetLastError();
|
2004-07-24 01:27:54 +00:00
|
|
|
return (HFILE)INVALID_HANDLE_VALUE;
|
2002-04-01 22:06:51 +00:00
|
|
|
}
|
2000-03-15 18:30:30 +00:00
|
|
|
|
2008-12-27 10:31:53 +00:00
|
|
|
if (uStyle & OF_DELETE)
|
|
|
|
{
|
|
|
|
if (!DeleteFileW(PathNameW))
|
|
|
|
{
|
|
|
|
lpReOpenBuff->nErrCode = GetLastError();
|
|
|
|
return HFILE_ERROR;
|
|
|
|
}
|
|
|
|
TRACE("(%s): OF_DELETE return = OK\n", lpFileName);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2002-04-01 22:06:51 +00:00
|
|
|
FileName.Buffer = lpReOpenBuff->szPathName;
|
|
|
|
FileName.Length = 0;
|
|
|
|
FileName.MaximumLength = OFS_MAXPATHNAME;
|
|
|
|
|
|
|
|
RtlInitUnicodeString(&FileNameU, PathNameW);
|
|
|
|
|
|
|
|
/* convert unicode string to ansi (or oem) */
|
|
|
|
if (bIsFileApiAnsi)
|
|
|
|
RtlUnicodeStringToAnsiString (&FileName, &FileNameU, FALSE);
|
|
|
|
else
|
|
|
|
RtlUnicodeStringToOemString (&FileName, &FileNameU, FALSE);
|
2000-03-15 18:30:30 +00:00
|
|
|
|
2005-12-17 15:45:59 +00:00
|
|
|
if (!RtlDosPathNameToNtPathName_U (PathNameW,
|
2002-04-01 22:06:51 +00:00
|
|
|
&FileNameString,
|
|
|
|
NULL,
|
|
|
|
NULL))
|
|
|
|
{
|
|
|
|
return (HFILE)INVALID_HANDLE_VALUE;
|
|
|
|
}
|
2000-03-15 18:30:30 +00:00
|
|
|
|
|
|
|
// FILE_SHARE_READ
|
|
|
|
// FILE_NO_INTERMEDIATE_BUFFERING
|
|
|
|
|
2004-05-25 20:04:14 +00:00
|
|
|
ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
|
|
|
|
ObjectAttributes.RootDirectory = NULL;
|
|
|
|
ObjectAttributes.ObjectName = &FileNameString;
|
|
|
|
ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT;
|
|
|
|
ObjectAttributes.SecurityDescriptor = NULL;
|
|
|
|
ObjectAttributes.SecurityQualityOfService = NULL;
|
|
|
|
|
2000-03-15 18:30:30 +00:00
|
|
|
errCode = NtOpenFile (&FileHandle,
|
|
|
|
GENERIC_READ|SYNCHRONIZE,
|
|
|
|
&ObjectAttributes,
|
|
|
|
&IoStatusBlock,
|
|
|
|
FILE_SHARE_READ,
|
2003-12-08 19:50:31 +00:00
|
|
|
FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT);
|
2000-03-15 18:30:30 +00:00
|
|
|
|
2008-12-27 10:31:53 +00:00
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameString.Buffer);
|
2002-04-01 22:06:51 +00:00
|
|
|
|
2008-12-27 10:31:53 +00:00
|
|
|
lpReOpenBuff->nErrCode = RtlNtStatusToDosError(errCode);
|
2000-03-15 18:30:30 +00:00
|
|
|
|
|
|
|
if (!NT_SUCCESS(errCode))
|
|
|
|
{
|
2000-06-03 14:47:33 +00:00
|
|
|
SetLastErrorByStatus (errCode);
|
2000-03-15 18:30:30 +00:00
|
|
|
return (HFILE)INVALID_HANDLE_VALUE;
|
|
|
|
}
|
|
|
|
|
2008-12-27 10:31:53 +00:00
|
|
|
if (uStyle & OF_EXIST)
|
|
|
|
{
|
|
|
|
NtClose(FileHandle);
|
2009-01-10 12:33:22 +00:00
|
|
|
return (HFILE)1;
|
2008-12-27 10:31:53 +00:00
|
|
|
}
|
|
|
|
|
2000-03-15 18:30:30 +00:00
|
|
|
return (HFILE)FileHandle;
|
1999-04-14 00:52:19 +00:00
|
|
|
}
|
|
|
|
|
1999-05-19 17:57:02 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-30 11:42:05 +00:00
|
|
|
BOOL WINAPI
|
2001-07-19 18:42:02 +00:00
|
|
|
FlushFileBuffers(HANDLE hFile)
|
1999-04-14 00:52:19 +00:00
|
|
|
{
|
|
|
|
NTSTATUS errCode;
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
2000-03-15 18:30:30 +00:00
|
|
|
|
2008-08-04 17:08:52 +00:00
|
|
|
hFile = TranslateStdHandle(hFile);
|
|
|
|
|
2002-05-07 22:21:47 +00:00
|
|
|
if (IsConsoleHandle(hFile))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
1999-04-14 00:52:19 +00:00
|
|
|
errCode = NtFlushBuffersFile(hFile,
|
|
|
|
&IoStatusBlock);
|
2000-03-15 18:30:30 +00:00
|
|
|
if (!NT_SUCCESS(errCode))
|
1999-02-07 00:37:29 +00:00
|
|
|
{
|
2000-06-03 14:47:33 +00:00
|
|
|
SetLastErrorByStatus(errCode);
|
1999-04-14 00:52:19 +00:00
|
|
|
return(FALSE);
|
1999-02-07 00:37:29 +00:00
|
|
|
}
|
1998-10-05 04:01:30 +00:00
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
|
1999-04-14 00:52:19 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-30 11:42:05 +00:00
|
|
|
DWORD WINAPI
|
2001-07-19 18:42:02 +00:00
|
|
|
SetFilePointer(HANDLE hFile,
|
2008-09-06 06:35:07 +00:00
|
|
|
LONG lDistanceToMove,
|
|
|
|
PLONG lpDistanceToMoveHigh,
|
|
|
|
DWORD dwMoveMethod)
|
1998-10-05 04:01:30 +00:00
|
|
|
{
|
1999-04-14 00:52:19 +00:00
|
|
|
FILE_POSITION_INFORMATION FilePosition;
|
2004-05-28 13:17:32 +00:00
|
|
|
FILE_STANDARD_INFORMATION FileStandard;
|
1998-10-05 04:01:30 +00:00
|
|
|
NTSTATUS errCode;
|
1999-04-14 00:52:19 +00:00
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
1999-05-19 17:57:02 +00:00
|
|
|
LARGE_INTEGER Distance;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2008-05-12 12:01:51 +00:00
|
|
|
TRACE("SetFilePointer(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n",
|
2008-09-06 06:35:07 +00:00
|
|
|
hFile,lDistanceToMove,dwMoveMethod);
|
1999-05-19 17:57:02 +00:00
|
|
|
|
2004-05-28 13:17:32 +00:00
|
|
|
if(IsConsoleHandle(hFile))
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
2008-09-06 06:35:07 +00:00
|
|
|
return INVALID_SET_FILE_POINTER;
|
2004-05-28 13:17:32 +00:00
|
|
|
}
|
2004-03-14 13:11:55 +00:00
|
|
|
|
2002-03-25 21:07:17 +00:00
|
|
|
if (lpDistanceToMoveHigh)
|
|
|
|
{
|
|
|
|
Distance.u.HighPart = *lpDistanceToMoveHigh;
|
2007-07-12 10:56:00 +00:00
|
|
|
Distance.u.LowPart = lDistanceToMove;
|
2002-03-25 21:07:17 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-07-12 10:56:00 +00:00
|
|
|
Distance.QuadPart = lDistanceToMove;
|
2002-03-25 21:07:17 +00:00
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-03-14 13:11:55 +00:00
|
|
|
switch(dwMoveMethod)
|
|
|
|
{
|
|
|
|
case FILE_CURRENT:
|
2008-09-06 06:35:07 +00:00
|
|
|
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;
|
2004-03-14 13:11:55 +00:00
|
|
|
case FILE_END:
|
2008-09-06 06:35:07 +00:00
|
|
|
errCode = NtQueryInformationFile(hFile,
|
1999-05-19 17:57:02 +00:00
|
|
|
&IoStatusBlock,
|
2004-05-28 13:17:32 +00:00
|
|
|
&FileStandard,
|
2001-08-06 18:35:15 +00:00
|
|
|
sizeof(FILE_STANDARD_INFORMATION),
|
|
|
|
FileStandardInformation);
|
2008-09-06 06:35:07 +00:00
|
|
|
FilePosition.CurrentByteOffset.QuadPart =
|
2004-05-28 13:17:32 +00:00
|
|
|
FileStandard.EndOfFile.QuadPart + Distance.QuadPart;
|
2008-09-06 06:35:07 +00:00
|
|
|
if (!NT_SUCCESS(errCode))
|
|
|
|
{
|
|
|
|
if (lpDistanceToMoveHigh != NULL)
|
|
|
|
*lpDistanceToMoveHigh = -1;
|
|
|
|
SetLastErrorByStatus(errCode);
|
|
|
|
return INVALID_SET_FILE_POINTER;
|
|
|
|
}
|
|
|
|
break;
|
2004-03-14 13:11:55 +00:00
|
|
|
case FILE_BEGIN:
|
1999-05-19 17:57:02 +00:00
|
|
|
FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart;
|
2008-09-06 06:35:07 +00:00
|
|
|
break;
|
2004-05-28 13:17:32 +00:00
|
|
|
default:
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
2008-09-06 06:35:07 +00:00
|
|
|
return INVALID_SET_FILE_POINTER;
|
2004-03-14 13:11:55 +00:00
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-03-14 13:11:55 +00:00
|
|
|
if(FilePosition.CurrentByteOffset.QuadPart < 0)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_NEGATIVE_SEEK);
|
2008-09-06 06:35:07 +00:00
|
|
|
return INVALID_SET_FILE_POINTER;
|
2004-03-14 13:11:55 +00:00
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2007-07-12 10:56:00 +00:00
|
|
|
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);
|
2008-09-06 06:35:07 +00:00
|
|
|
return INVALID_SET_FILE_POINTER;
|
2007-07-12 10:56:00 +00:00
|
|
|
}
|
|
|
|
|
1999-04-14 00:52:19 +00:00
|
|
|
errCode = NtSetInformationFile(hFile,
|
2008-09-06 06:35:07 +00:00
|
|
|
&IoStatusBlock,
|
|
|
|
&FilePosition,
|
|
|
|
sizeof(FILE_POSITION_INFORMATION),
|
|
|
|
FilePositionInformation);
|
2000-03-15 18:30:30 +00:00
|
|
|
if (!NT_SUCCESS(errCode))
|
1999-02-07 00:37:29 +00:00
|
|
|
{
|
2007-07-12 10:56:00 +00:00
|
|
|
if (lpDistanceToMoveHigh != NULL)
|
|
|
|
*lpDistanceToMoveHigh = -1;
|
|
|
|
|
|
|
|
SetLastErrorByStatus(errCode);
|
2008-09-06 06:35:07 +00:00
|
|
|
return INVALID_SET_FILE_POINTER;
|
1999-02-07 00:37:29 +00:00
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2000-10-01 19:54:57 +00:00
|
|
|
if (lpDistanceToMoveHigh != NULL)
|
1999-04-14 00:52:19 +00:00
|
|
|
{
|
1999-05-11 19:32:15 +00:00
|
|
|
*lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart;
|
1999-04-14 00:52:19 +00:00
|
|
|
}
|
2007-07-12 10:56:00 +00:00
|
|
|
|
2009-09-27 20:07:43 +00:00
|
|
|
if (FilePosition.CurrentByteOffset.u.LowPart == MAXDWORD)
|
2007-07-12 10:56:00 +00:00
|
|
|
{
|
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
|
1999-05-11 19:32:15 +00:00
|
|
|
return FilePosition.CurrentByteOffset.u.LowPart;
|
1999-03-19 05:55:55 +00:00
|
|
|
}
|
1999-02-05 19:24:10 +00:00
|
|
|
|
1999-05-19 17:57:02 +00:00
|
|
|
|
2004-03-14 13:11:55 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
BOOL
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2004-03-14 13:11:55 +00:00
|
|
|
SetFilePointerEx(HANDLE hFile,
|
|
|
|
LARGE_INTEGER liDistanceToMove,
|
|
|
|
PLARGE_INTEGER lpNewFilePointer,
|
|
|
|
DWORD dwMoveMethod)
|
|
|
|
{
|
|
|
|
FILE_POSITION_INFORMATION FilePosition;
|
2004-05-28 13:17:32 +00:00
|
|
|
FILE_STANDARD_INFORMATION FileStandard;
|
2004-03-14 13:11:55 +00:00
|
|
|
NTSTATUS errCode;
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
|
2004-05-28 13:17:32 +00:00
|
|
|
if(IsConsoleHandle(hFile))
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2004-03-14 13:11:55 +00:00
|
|
|
|
|
|
|
switch(dwMoveMethod)
|
|
|
|
{
|
|
|
|
case FILE_CURRENT:
|
|
|
|
NtQueryInformationFile(hFile,
|
|
|
|
&IoStatusBlock,
|
|
|
|
&FilePosition,
|
|
|
|
sizeof(FILE_POSITION_INFORMATION),
|
|
|
|
FilePositionInformation);
|
|
|
|
FilePosition.CurrentByteOffset.QuadPart += liDistanceToMove.QuadPart;
|
|
|
|
break;
|
|
|
|
case FILE_END:
|
|
|
|
NtQueryInformationFile(hFile,
|
|
|
|
&IoStatusBlock,
|
2004-05-28 13:17:32 +00:00
|
|
|
&FileStandard,
|
2004-03-14 13:11:55 +00:00
|
|
|
sizeof(FILE_STANDARD_INFORMATION),
|
|
|
|
FileStandardInformation);
|
|
|
|
FilePosition.CurrentByteOffset.QuadPart =
|
2004-05-28 13:17:32 +00:00
|
|
|
FileStandard.EndOfFile.QuadPart + liDistanceToMove.QuadPart;
|
2004-03-14 13:11:55 +00:00
|
|
|
break;
|
|
|
|
case FILE_BEGIN:
|
|
|
|
FilePosition.CurrentByteOffset.QuadPart = liDistanceToMove.QuadPart;
|
|
|
|
break;
|
2004-05-28 13:17:32 +00:00
|
|
|
default:
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
2004-03-14 13:11:55 +00:00
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-03-14 13:11:55 +00:00
|
|
|
if(FilePosition.CurrentByteOffset.QuadPart < 0)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_NEGATIVE_SEEK);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-03-14 13:11:55 +00:00
|
|
|
errCode = NtSetInformationFile(hFile,
|
|
|
|
&IoStatusBlock,
|
|
|
|
&FilePosition,
|
|
|
|
sizeof(FILE_POSITION_INFORMATION),
|
|
|
|
FilePositionInformation);
|
|
|
|
if (!NT_SUCCESS(errCode))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(errCode);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-03-14 13:11:55 +00:00
|
|
|
if (lpNewFilePointer)
|
|
|
|
{
|
|
|
|
*lpNewFilePointer = FilePosition.CurrentByteOffset;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-30 11:42:05 +00:00
|
|
|
DWORD WINAPI
|
2001-07-19 18:42:02 +00:00
|
|
|
GetFileType(HANDLE hFile)
|
1999-03-19 05:55:55 +00:00
|
|
|
{
|
2003-03-06 13:01:15 +00:00
|
|
|
FILE_FS_DEVICE_INFORMATION DeviceInfo;
|
|
|
|
IO_STATUS_BLOCK StatusBlock;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
/* Get real handle */
|
2008-08-04 17:08:52 +00:00
|
|
|
hFile = TranslateStdHandle(hFile);
|
2003-03-06 13:01:15 +00:00
|
|
|
|
|
|
|
/* Check for console handle */
|
|
|
|
if (IsConsoleHandle(hFile))
|
|
|
|
{
|
|
|
|
if (VerifyConsoleIoHandle(hFile))
|
|
|
|
return FILE_TYPE_CHAR;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = NtQueryVolumeInformationFile(hFile,
|
|
|
|
&StatusBlock,
|
|
|
|
&DeviceInfo,
|
|
|
|
sizeof(FILE_FS_DEVICE_INFORMATION),
|
|
|
|
FileFsDeviceInformation);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return FILE_TYPE_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (DeviceInfo.DeviceType)
|
|
|
|
{
|
|
|
|
case FILE_DEVICE_CD_ROM:
|
|
|
|
case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
|
|
|
|
case FILE_DEVICE_CONTROLLER:
|
|
|
|
case FILE_DEVICE_DATALINK:
|
|
|
|
case FILE_DEVICE_DFS:
|
|
|
|
case FILE_DEVICE_DISK:
|
|
|
|
case FILE_DEVICE_DISK_FILE_SYSTEM:
|
|
|
|
case FILE_DEVICE_VIRTUAL_DISK:
|
|
|
|
return FILE_TYPE_DISK;
|
|
|
|
|
|
|
|
case FILE_DEVICE_KEYBOARD:
|
|
|
|
case FILE_DEVICE_MOUSE:
|
|
|
|
case FILE_DEVICE_NULL:
|
|
|
|
case FILE_DEVICE_PARALLEL_PORT:
|
|
|
|
case FILE_DEVICE_PRINTER:
|
|
|
|
case FILE_DEVICE_SERIAL_PORT:
|
|
|
|
case FILE_DEVICE_SCREEN:
|
|
|
|
case FILE_DEVICE_SOUND:
|
|
|
|
case FILE_DEVICE_MODEM:
|
|
|
|
return FILE_TYPE_CHAR;
|
|
|
|
|
|
|
|
case FILE_DEVICE_NAMED_PIPE:
|
|
|
|
return FILE_TYPE_PIPE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FILE_TYPE_UNKNOWN;
|
1998-10-05 04:01:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-30 11:42:05 +00:00
|
|
|
DWORD WINAPI
|
2001-07-19 18:42:02 +00:00
|
|
|
GetFileSize(HANDLE hFile,
|
|
|
|
LPDWORD lpFileSizeHigh)
|
1999-04-14 00:52:19 +00:00
|
|
|
{
|
|
|
|
NTSTATUS errCode;
|
|
|
|
FILE_STANDARD_INFORMATION FileStandard;
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
1998-10-05 04:01:30 +00:00
|
|
|
|
1999-04-14 00:52:19 +00:00
|
|
|
errCode = NtQueryInformationFile(hFile,
|
|
|
|
&IoStatusBlock,
|
2000-10-01 19:54:57 +00:00
|
|
|
&FileStandard,
|
1999-04-14 00:52:19 +00:00
|
|
|
sizeof(FILE_STANDARD_INFORMATION),
|
|
|
|
FileStandardInformation);
|
2000-10-01 19:54:57 +00:00
|
|
|
if (!NT_SUCCESS(errCode))
|
1999-04-14 00:52:19 +00:00
|
|
|
{
|
2000-06-03 14:47:33 +00:00
|
|
|
SetLastErrorByStatus(errCode);
|
2000-10-01 19:54:57 +00:00
|
|
|
if ( lpFileSizeHigh == NULL )
|
1999-04-14 00:52:19 +00:00
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( lpFileSizeHigh != NULL )
|
2002-06-07 16:54:04 +00:00
|
|
|
*lpFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
|
1999-04-14 00:52:19 +00:00
|
|
|
|
2002-06-07 16:54:04 +00:00
|
|
|
return FileStandard.EndOfFile.u.LowPart;
|
1998-10-05 04:01:30 +00:00
|
|
|
}
|
|
|
|
|
1999-05-19 17:57:02 +00:00
|
|
|
|
2004-03-14 13:20:10 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
BOOL
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2004-03-14 13:20:10 +00:00
|
|
|
GetFileSizeEx(
|
|
|
|
HANDLE hFile,
|
|
|
|
PLARGE_INTEGER lpFileSize
|
|
|
|
)
|
|
|
|
{
|
|
|
|
NTSTATUS errCode;
|
|
|
|
FILE_STANDARD_INFORMATION FileStandard;
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
|
|
|
|
errCode = NtQueryInformationFile(hFile,
|
|
|
|
&IoStatusBlock,
|
|
|
|
&FileStandard,
|
|
|
|
sizeof(FILE_STANDARD_INFORMATION),
|
|
|
|
FileStandardInformation);
|
|
|
|
if (!NT_SUCCESS(errCode))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(errCode);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (lpFileSize)
|
|
|
|
*lpFileSize = FileStandard.EndOfFile;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-30 11:42:05 +00:00
|
|
|
DWORD WINAPI
|
2001-07-19 18:42:02 +00:00
|
|
|
GetCompressedFileSizeA(LPCSTR lpFileName,
|
|
|
|
LPDWORD lpFileSizeHigh)
|
1998-10-05 04:01:30 +00:00
|
|
|
{
|
2005-03-15 19:40:22 +00:00
|
|
|
PWCHAR FileNameW;
|
2000-10-01 19:54:57 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
|
|
|
|
return INVALID_FILE_SIZE;
|
2000-10-01 19:54:57 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
return GetCompressedFileSizeW(FileNameW, lpFileSizeHigh);
|
1998-10-05 04:01:30 +00:00
|
|
|
}
|
|
|
|
|
1999-05-19 17:57:02 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-30 11:42:05 +00:00
|
|
|
DWORD WINAPI
|
2001-07-19 18:42:02 +00:00
|
|
|
GetCompressedFileSizeW(LPCWSTR lpFileName,
|
|
|
|
LPDWORD lpFileSizeHigh)
|
1998-10-05 04:01:30 +00:00
|
|
|
{
|
1999-04-14 00:52:19 +00:00
|
|
|
FILE_COMPRESSION_INFORMATION FileCompression;
|
|
|
|
NTSTATUS errCode;
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
HANDLE hFile;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2000-10-01 19:54:57 +00:00
|
|
|
hFile = CreateFileW(lpFileName,
|
|
|
|
GENERIC_READ,
|
|
|
|
FILE_SHARE_READ,
|
|
|
|
NULL,
|
|
|
|
OPEN_EXISTING,
|
|
|
|
FILE_ATTRIBUTE_NORMAL,
|
1999-04-14 00:52:19 +00:00
|
|
|
NULL);
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
|
|
return INVALID_FILE_SIZE;
|
1998-10-05 04:01:30 +00:00
|
|
|
|
1999-04-14 00:52:19 +00:00
|
|
|
errCode = NtQueryInformationFile(hFile,
|
|
|
|
&IoStatusBlock,
|
2000-10-01 19:54:57 +00:00
|
|
|
&FileCompression,
|
1999-04-14 00:52:19 +00:00
|
|
|
sizeof(FILE_COMPRESSION_INFORMATION),
|
|
|
|
FileCompressionInformation);
|
2005-03-15 19:40:22 +00:00
|
|
|
|
|
|
|
CloseHandle(hFile);
|
|
|
|
|
2000-10-01 19:54:57 +00:00
|
|
|
if (!NT_SUCCESS(errCode))
|
1999-04-14 00:52:19 +00:00
|
|
|
{
|
2000-06-03 14:47:33 +00:00
|
|
|
SetLastErrorByStatus(errCode);
|
2003-02-12 00:39:31 +00:00
|
|
|
return INVALID_FILE_SIZE;
|
1999-04-14 00:52:19 +00:00
|
|
|
}
|
2003-02-12 00:39:31 +00:00
|
|
|
|
|
|
|
if(lpFileSizeHigh)
|
|
|
|
*lpFileSizeHigh = FileCompression.CompressedFileSize.u.HighPart;
|
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
SetLastError(NO_ERROR);
|
2003-02-12 00:39:31 +00:00
|
|
|
return FileCompression.CompressedFileSize.u.LowPart;
|
1998-10-05 04:01:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-30 11:42:05 +00:00
|
|
|
BOOL WINAPI
|
2001-07-19 18:42:02 +00:00
|
|
|
GetFileInformationByHandle(HANDLE hFile,
|
|
|
|
LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
|
1998-10-05 04:01:30 +00:00
|
|
|
{
|
2001-11-01 10:35:15 +00:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
FILE_FS_VOLUME_INFORMATION FileFsVolume;
|
|
|
|
WCHAR Name[255];
|
|
|
|
}
|
|
|
|
FileFsVolume;
|
|
|
|
|
|
|
|
FILE_BASIC_INFORMATION FileBasic;
|
1999-04-14 00:52:19 +00:00
|
|
|
FILE_INTERNAL_INFORMATION FileInternal;
|
|
|
|
FILE_STANDARD_INFORMATION FileStandard;
|
1998-10-05 04:01:30 +00:00
|
|
|
NTSTATUS errCode;
|
1999-04-14 00:52:19 +00:00
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
2001-11-01 10:35:15 +00:00
|
|
|
|
2004-05-28 13:17:32 +00:00
|
|
|
if(IsConsoleHandle(hFile))
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
1999-04-14 00:52:19 +00:00
|
|
|
errCode = NtQueryInformationFile(hFile,
|
|
|
|
&IoStatusBlock,
|
2001-11-01 10:35:15 +00:00
|
|
|
&FileBasic,
|
|
|
|
sizeof(FILE_BASIC_INFORMATION),
|
|
|
|
FileBasicInformation);
|
2000-10-01 19:54:57 +00:00
|
|
|
if (!NT_SUCCESS(errCode))
|
1998-10-05 04:01:30 +00:00
|
|
|
{
|
2000-06-03 14:47:33 +00:00
|
|
|
SetLastErrorByStatus(errCode);
|
1998-10-05 04:01:30 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
1999-05-19 17:57:02 +00:00
|
|
|
|
2001-11-01 10:35:15 +00:00
|
|
|
lpFileInformation->dwFileAttributes = (DWORD)FileBasic.FileAttributes;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-09-06 15:56:25 +00:00
|
|
|
lpFileInformation->ftCreationTime.dwHighDateTime = FileBasic.CreationTime.u.HighPart;
|
|
|
|
lpFileInformation->ftCreationTime.dwLowDateTime = FileBasic.CreationTime.u.LowPart;
|
|
|
|
|
|
|
|
lpFileInformation->ftLastAccessTime.dwHighDateTime = FileBasic.LastAccessTime.u.HighPart;
|
|
|
|
lpFileInformation->ftLastAccessTime.dwLowDateTime = FileBasic.LastAccessTime.u.LowPart;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-09-06 15:56:25 +00:00
|
|
|
lpFileInformation->ftLastWriteTime.dwHighDateTime = FileBasic.LastWriteTime.u.HighPart;
|
|
|
|
lpFileInformation->ftLastWriteTime.dwLowDateTime = FileBasic.LastWriteTime.u.LowPart;
|
2001-11-01 10:35:15 +00:00
|
|
|
|
1999-04-14 00:52:19 +00:00
|
|
|
errCode = NtQueryInformationFile(hFile,
|
|
|
|
&IoStatusBlock,
|
2000-10-01 19:54:57 +00:00
|
|
|
&FileInternal,
|
1999-04-14 00:52:19 +00:00
|
|
|
sizeof(FILE_INTERNAL_INFORMATION),
|
|
|
|
FileInternalInformation);
|
2000-10-01 19:54:57 +00:00
|
|
|
if (!NT_SUCCESS(errCode))
|
1998-10-05 04:01:30 +00:00
|
|
|
{
|
2000-06-03 14:47:33 +00:00
|
|
|
SetLastErrorByStatus(errCode);
|
1998-10-05 04:01:30 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
1999-05-19 17:57:02 +00:00
|
|
|
|
1999-05-11 19:32:15 +00:00
|
|
|
lpFileInformation->nFileIndexHigh = FileInternal.IndexNumber.u.HighPart;
|
|
|
|
lpFileInformation->nFileIndexLow = FileInternal.IndexNumber.u.LowPart;
|
2001-11-01 10:35:15 +00:00
|
|
|
|
1999-04-14 00:52:19 +00:00
|
|
|
errCode = NtQueryVolumeInformationFile(hFile,
|
|
|
|
&IoStatusBlock,
|
2000-10-01 19:54:57 +00:00
|
|
|
&FileFsVolume,
|
2001-11-01 10:35:15 +00:00
|
|
|
sizeof(FileFsVolume),
|
1999-04-14 00:52:19 +00:00
|
|
|
FileFsVolumeInformation);
|
2000-10-01 19:54:57 +00:00
|
|
|
if (!NT_SUCCESS(errCode))
|
1999-04-14 00:52:19 +00:00
|
|
|
{
|
2000-06-03 14:47:33 +00:00
|
|
|
SetLastErrorByStatus(errCode);
|
1999-04-14 00:52:19 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
1999-05-19 17:57:02 +00:00
|
|
|
|
2001-11-01 10:35:15 +00:00
|
|
|
lpFileInformation->dwVolumeSerialNumber = FileFsVolume.FileFsVolume.VolumeSerialNumber;
|
|
|
|
|
1999-04-14 00:52:19 +00:00
|
|
|
errCode = NtQueryInformationFile(hFile,
|
|
|
|
&IoStatusBlock,
|
2000-10-01 19:54:57 +00:00
|
|
|
&FileStandard,
|
1999-04-14 00:52:19 +00:00
|
|
|
sizeof(FILE_STANDARD_INFORMATION),
|
|
|
|
FileStandardInformation);
|
|
|
|
if (!NT_SUCCESS(errCode))
|
|
|
|
{
|
2000-06-03 14:47:33 +00:00
|
|
|
SetLastErrorByStatus(errCode);
|
1999-04-14 00:52:19 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
1998-12-04 18:28:13 +00:00
|
|
|
|
1999-05-19 17:57:02 +00:00
|
|
|
lpFileInformation->nNumberOfLinks = FileStandard.NumberOfLinks;
|
2002-05-27 18:23:49 +00:00
|
|
|
lpFileInformation->nFileSizeHigh = FileStandard.EndOfFile.u.HighPart;
|
|
|
|
lpFileInformation->nFileSizeLow = FileStandard.EndOfFile.u.LowPart;
|
1998-12-04 18:28:13 +00:00
|
|
|
|
1999-05-19 17:57:02 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
1998-12-04 18:28:13 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-30 11:42:05 +00:00
|
|
|
BOOL WINAPI
|
2005-05-09 01:46:57 +00:00
|
|
|
GetFileAttributesExW(LPCWSTR lpFileName,
|
|
|
|
GET_FILEEX_INFO_LEVELS fInfoLevelId,
|
2003-06-09 19:58:21 +00:00
|
|
|
LPVOID lpFileInformation)
|
1998-12-04 18:28:13 +00:00
|
|
|
{
|
2003-06-09 19:58:21 +00:00
|
|
|
FILE_NETWORK_OPEN_INFORMATION FileInformation;
|
2003-03-23 04:01:16 +00:00
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
UNICODE_STRING FileName;
|
|
|
|
NTSTATUS Status;
|
2003-06-09 19:58:21 +00:00
|
|
|
WIN32_FILE_ATTRIBUTE_DATA* FileAttributeData;
|
1998-12-04 18:28:13 +00:00
|
|
|
|
2008-05-12 12:01:51 +00:00
|
|
|
TRACE("GetFileAttributesExW(%S) called\n", lpFileName);
|
2003-06-09 19:58:21 +00:00
|
|
|
|
|
|
|
|
|
|
|
if (fInfoLevelId != GetFileExInfoStandard || lpFileInformation == NULL)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
1999-12-24 17:16:32 +00:00
|
|
|
|
2003-03-23 04:01:16 +00:00
|
|
|
/* Validate and translate the filename */
|
2005-12-17 15:45:59 +00:00
|
|
|
if (!RtlDosPathNameToNtPathName_U (lpFileName,
|
2003-03-23 04:01:16 +00:00
|
|
|
&FileName,
|
|
|
|
NULL,
|
|
|
|
NULL))
|
|
|
|
{
|
2008-05-12 12:01:51 +00:00
|
|
|
WARN ("Invalid path '%S'\n", lpFileName);
|
2003-03-23 04:01:16 +00:00
|
|
|
SetLastError (ERROR_BAD_PATHNAME);
|
2003-06-09 19:58:21 +00:00
|
|
|
return FALSE;
|
2003-03-23 04:01:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* build the object attributes */
|
|
|
|
InitializeObjectAttributes (&ObjectAttributes,
|
|
|
|
&FileName,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
/* Get file attributes */
|
2005-09-24 18:09:06 +00:00
|
|
|
Status = NtQueryFullAttributesFile(&ObjectAttributes,
|
|
|
|
&FileInformation);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2005-09-24 18:09:06 +00:00
|
|
|
RtlFreeUnicodeString (&FileName);
|
2003-03-23 04:01:16 +00:00
|
|
|
if (!NT_SUCCESS (Status))
|
|
|
|
{
|
2008-05-12 12:01:51 +00:00
|
|
|
WARN ("NtQueryFullAttributesFile() failed (Status %lx)\n", Status);
|
2003-03-23 04:01:16 +00:00
|
|
|
SetLastErrorByStatus (Status);
|
2003-06-09 19:58:21 +00:00
|
|
|
return FALSE;
|
2003-03-23 04:01:16 +00:00
|
|
|
}
|
|
|
|
|
2003-06-09 19:58:21 +00:00
|
|
|
FileAttributeData = (WIN32_FILE_ATTRIBUTE_DATA*)lpFileInformation;
|
|
|
|
FileAttributeData->dwFileAttributes = FileInformation.FileAttributes;
|
|
|
|
FileAttributeData->ftCreationTime.dwLowDateTime = FileInformation.CreationTime.u.LowPart;
|
|
|
|
FileAttributeData->ftCreationTime.dwHighDateTime = FileInformation.CreationTime.u.HighPart;
|
|
|
|
FileAttributeData->ftLastAccessTime.dwLowDateTime = FileInformation.LastAccessTime.u.LowPart;
|
|
|
|
FileAttributeData->ftLastAccessTime.dwHighDateTime = FileInformation.LastAccessTime.u.HighPart;
|
|
|
|
FileAttributeData->ftLastWriteTime.dwLowDateTime = FileInformation.LastWriteTime.u.LowPart;
|
|
|
|
FileAttributeData->ftLastWriteTime.dwHighDateTime = FileInformation.LastWriteTime.u.HighPart;
|
|
|
|
FileAttributeData->nFileSizeLow = FileInformation.EndOfFile.u.LowPart;
|
|
|
|
FileAttributeData->nFileSizeHigh = FileInformation.EndOfFile.u.HighPart;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-30 11:42:05 +00:00
|
|
|
BOOL WINAPI
|
2003-06-09 19:58:21 +00:00
|
|
|
GetFileAttributesExA(LPCSTR lpFileName,
|
2005-05-09 01:46:57 +00:00
|
|
|
GET_FILEEX_INFO_LEVELS fInfoLevelId,
|
2003-06-09 19:58:21 +00:00
|
|
|
LPVOID lpFileInformation)
|
|
|
|
{
|
2005-03-15 19:40:22 +00:00
|
|
|
PWCHAR FileNameW;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
|
|
|
|
return FALSE;
|
2003-06-09 19:58:21 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
return GetFileAttributesExW(FileNameW, fInfoLevelId, lpFileInformation);
|
1998-12-04 18:28:13 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-30 11:42:05 +00:00
|
|
|
DWORD WINAPI
|
2003-06-09 19:58:21 +00:00
|
|
|
GetFileAttributesA(LPCSTR lpFileName)
|
|
|
|
{
|
2005-03-15 19:40:22 +00:00
|
|
|
WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
|
|
|
|
PWSTR FileNameW;
|
2009-08-11 14:19:43 +00:00
|
|
|
BOOL ret;
|
2003-06-09 19:58:21 +00:00
|
|
|
|
2009-08-11 14:19:43 +00:00
|
|
|
if (!lpFileName || !(FileNameW = FilenameA2W(lpFileName, FALSE)))
|
2005-03-15 19:40:22 +00:00
|
|
|
return INVALID_FILE_ATTRIBUTES;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
ret = GetFileAttributesExW(FileNameW, GetFileExInfoStandard, &FileAttributeData);
|
2003-06-09 19:58:21 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
return ret ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES;
|
2003-06-09 19:58:21 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-30 11:42:05 +00:00
|
|
|
DWORD WINAPI
|
2003-06-09 19:58:21 +00:00
|
|
|
GetFileAttributesW(LPCWSTR lpFileName)
|
|
|
|
{
|
|
|
|
WIN32_FILE_ATTRIBUTE_DATA FileAttributeData;
|
|
|
|
BOOL Result;
|
|
|
|
|
2008-05-12 12:01:51 +00:00
|
|
|
TRACE ("GetFileAttributeW(%S) called\n", lpFileName);
|
2003-06-09 19:58:21 +00:00
|
|
|
|
|
|
|
Result = GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &FileAttributeData);
|
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
return Result ? FileAttributeData.dwFileAttributes : INVALID_FILE_ATTRIBUTES;
|
2003-06-09 19:58:21 +00:00
|
|
|
}
|
1999-05-19 17:57:02 +00:00
|
|
|
|
2005-08-24 23:59:03 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-30 11:42:05 +00:00
|
|
|
BOOL WINAPI
|
2005-08-24 23:59:03 +00:00
|
|
|
GetFileAttributesByHandle(IN HANDLE hFile,
|
|
|
|
OUT LPDWORD dwFileAttributes,
|
|
|
|
IN DWORD dwFlags)
|
|
|
|
{
|
|
|
|
FILE_BASIC_INFORMATION FileBasic;
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
NTSTATUS Status;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2005-08-24 23:59:03 +00:00
|
|
|
UNREFERENCED_PARAMETER(dwFlags);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2005-08-25 00:33:37 +00:00
|
|
|
if (IsConsoleHandle(hFile))
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2005-08-24 23:59:03 +00:00
|
|
|
Status = NtQueryInformationFile(hFile,
|
|
|
|
&IoStatusBlock,
|
|
|
|
&FileBasic,
|
|
|
|
sizeof(FileBasic),
|
|
|
|
FileBasicInformation);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
*dwFileAttributes = FileBasic.FileAttributes;
|
|
|
|
return TRUE;
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2005-08-24 23:59:03 +00:00
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-30 11:42:05 +00:00
|
|
|
BOOL WINAPI
|
2005-08-24 23:59:03 +00:00
|
|
|
SetFileAttributesByHandle(IN HANDLE hFile,
|
|
|
|
IN DWORD dwFileAttributes,
|
|
|
|
IN DWORD dwFlags)
|
|
|
|
{
|
|
|
|
FILE_BASIC_INFORMATION FileBasic;
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
UNREFERENCED_PARAMETER(dwFlags);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2005-08-25 00:33:37 +00:00
|
|
|
if (IsConsoleHandle(hFile))
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2005-08-24 23:59:03 +00:00
|
|
|
|
|
|
|
Status = NtQueryInformationFile(hFile,
|
|
|
|
&IoStatusBlock,
|
|
|
|
&FileBasic,
|
|
|
|
sizeof(FileBasic),
|
|
|
|
FileBasicInformation);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
FileBasic.FileAttributes = dwFileAttributes;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2005-08-24 23:59:03 +00:00
|
|
|
Status = NtSetInformationFile(hFile,
|
|
|
|
&IoStatusBlock,
|
|
|
|
&FileBasic,
|
|
|
|
sizeof(FileBasic),
|
|
|
|
FileBasicInformation);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2005-08-24 23:59:03 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-30 11:42:05 +00:00
|
|
|
BOOL WINAPI
|
2005-03-15 19:40:22 +00:00
|
|
|
SetFileAttributesA(
|
|
|
|
LPCSTR lpFileName,
|
|
|
|
DWORD dwFileAttributes)
|
1999-01-16 02:11:45 +00:00
|
|
|
{
|
2005-03-15 19:40:22 +00:00
|
|
|
PWCHAR FileNameW;
|
2000-03-15 18:30:30 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
|
|
|
|
return FALSE;
|
2000-03-15 18:30:30 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
return SetFileAttributesW(FileNameW, dwFileAttributes);
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-30 11:42:05 +00:00
|
|
|
BOOL WINAPI
|
2001-07-19 18:42:02 +00:00
|
|
|
SetFileAttributesW(LPCWSTR lpFileName,
|
|
|
|
DWORD dwFileAttributes)
|
1999-01-16 02:11:45 +00:00
|
|
|
{
|
2003-03-23 04:01:16 +00:00
|
|
|
FILE_BASIC_INFORMATION FileInformation;
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
UNICODE_STRING FileName;
|
|
|
|
HANDLE FileHandle;
|
|
|
|
NTSTATUS Status;
|
1999-03-19 05:55:55 +00:00
|
|
|
|
2008-05-12 12:01:51 +00:00
|
|
|
TRACE ("SetFileAttributeW(%S, 0x%lx) called\n", lpFileName, dwFileAttributes);
|
2003-03-23 04:01:16 +00:00
|
|
|
|
|
|
|
/* Validate and translate the filename */
|
2005-12-17 15:45:59 +00:00
|
|
|
if (!RtlDosPathNameToNtPathName_U (lpFileName,
|
2003-03-23 04:01:16 +00:00
|
|
|
&FileName,
|
|
|
|
NULL,
|
|
|
|
NULL))
|
|
|
|
{
|
2008-05-12 12:01:51 +00:00
|
|
|
WARN ("Invalid path\n");
|
2003-03-23 04:01:16 +00:00
|
|
|
SetLastError (ERROR_BAD_PATHNAME);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2008-05-12 12:01:51 +00:00
|
|
|
TRACE ("FileName: \'%wZ\'\n", &FileName);
|
2003-03-23 04:01:16 +00:00
|
|
|
|
|
|
|
/* build the object attributes */
|
|
|
|
InitializeObjectAttributes (&ObjectAttributes,
|
|
|
|
&FileName,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
/* Open the file */
|
|
|
|
Status = NtOpenFile (&FileHandle,
|
|
|
|
SYNCHRONIZE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
|
|
|
|
&ObjectAttributes,
|
|
|
|
&IoStatusBlock,
|
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
|
|
FILE_SYNCHRONOUS_IO_NONALERT);
|
|
|
|
RtlFreeUnicodeString (&FileName);
|
|
|
|
if (!NT_SUCCESS (Status))
|
|
|
|
{
|
2008-05-12 12:01:51 +00:00
|
|
|
WARN ("NtOpenFile() failed (Status %lx)\n", Status);
|
2003-03-23 04:01:16 +00:00
|
|
|
SetLastErrorByStatus (Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = NtQueryInformationFile(FileHandle,
|
1999-03-19 05:55:55 +00:00
|
|
|
&IoStatusBlock,
|
2003-03-23 04:01:16 +00:00
|
|
|
&FileInformation,
|
1999-03-19 05:55:55 +00:00
|
|
|
sizeof(FILE_BASIC_INFORMATION),
|
|
|
|
FileBasicInformation);
|
2003-03-23 04:01:16 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2008-05-12 12:01:51 +00:00
|
|
|
WARN ("SetFileAttributes NtQueryInformationFile failed with status 0x%08x\n", Status);
|
2003-03-23 04:01:16 +00:00
|
|
|
NtClose (FileHandle);
|
|
|
|
SetLastErrorByStatus (Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
FileInformation.FileAttributes = dwFileAttributes;
|
|
|
|
Status = NtSetInformationFile(FileHandle,
|
|
|
|
&IoStatusBlock,
|
|
|
|
&FileInformation,
|
|
|
|
sizeof(FILE_BASIC_INFORMATION),
|
|
|
|
FileBasicInformation);
|
|
|
|
NtClose (FileHandle);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2008-05-12 12:01:51 +00:00
|
|
|
WARN ("SetFileAttributes NtSetInformationFile failed with status 0x%08x\n", Status);
|
2003-03-23 04:01:16 +00:00
|
|
|
SetLastErrorByStatus (Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
|
|
|
|
1998-12-04 18:28:13 +00:00
|
|
|
|
2002-04-27 19:15:00 +00:00
|
|
|
|
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* GetTempFileNameA (KERNEL32.@)
|
|
|
|
*/
|
|
|
|
UINT WINAPI GetTempFileNameA( LPCSTR path, LPCSTR prefix, UINT unique, LPSTR buffer)
|
|
|
|
{
|
|
|
|
WCHAR BufferW[MAX_PATH];
|
|
|
|
PWCHAR PathW;
|
|
|
|
WCHAR PrefixW[3+1];
|
|
|
|
UINT ret;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
if (!(PathW = FilenameA2W(path, FALSE)))
|
|
|
|
return 0;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
if (prefix)
|
|
|
|
FilenameA2W_N(PrefixW, 3+1, prefix, -1);
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
ret = GetTempFileNameW(PathW, prefix ? PrefixW : NULL, unique, BufferW);
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
if (ret)
|
|
|
|
FilenameW2A_N(buffer, MAX_PATH, BufferW, -1);
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
return ret;
|
1998-12-04 18:28:13 +00:00
|
|
|
}
|
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* GetTempFileNameW (KERNEL32.@)
|
2003-07-10 18:50:51 +00:00
|
|
|
*/
|
2005-03-15 19:40:22 +00:00
|
|
|
UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique, LPWSTR buffer )
|
1998-12-04 18:28:13 +00:00
|
|
|
{
|
2005-03-15 19:40:22 +00:00
|
|
|
static const WCHAR formatW[] = L"%x.tmp";
|
2002-04-27 19:15:00 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
int i;
|
|
|
|
LPWSTR p;
|
2002-04-27 19:15:00 +00:00
|
|
|
|
2007-07-13 20:23:26 +00:00
|
|
|
if ( !path || !buffer )
|
2005-03-15 19:40:22 +00:00
|
|
|
{
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
wcscpy( buffer, path );
|
|
|
|
p = buffer + wcslen(buffer);
|
|
|
|
|
|
|
|
/* add a \, if there isn't one */
|
|
|
|
if ((p == buffer) || (p[-1] != '\\')) *p++ = '\\';
|
|
|
|
|
2007-07-13 20:23:26 +00:00
|
|
|
if ( prefix )
|
|
|
|
for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++;
|
2005-03-15 19:40:22 +00:00
|
|
|
|
|
|
|
unique &= 0xffff;
|
|
|
|
|
|
|
|
if (unique) swprintf( p, formatW, unique );
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* get a "random" unique number and try to create the file */
|
|
|
|
HANDLE handle;
|
|
|
|
UINT num = GetTickCount() & 0xffff;
|
|
|
|
|
|
|
|
if (!num) num = 1;
|
|
|
|
unique = num;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
swprintf( p, formatW, unique );
|
|
|
|
handle = CreateFileW( buffer, GENERIC_WRITE, 0, NULL,
|
|
|
|
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
|
|
|
|
if (handle != INVALID_HANDLE_VALUE)
|
|
|
|
{ /* We created it */
|
2008-05-12 12:01:51 +00:00
|
|
|
TRACE("created %S\n", buffer);
|
2005-03-15 19:40:22 +00:00
|
|
|
CloseHandle( handle );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (GetLastError() != ERROR_FILE_EXISTS &&
|
|
|
|
GetLastError() != ERROR_SHARING_VIOLATION)
|
|
|
|
break; /* No need to go on */
|
|
|
|
if (!(++unique & 0xffff)) unique = 1;
|
|
|
|
} while (unique != num);
|
|
|
|
}
|
|
|
|
|
2008-05-12 12:01:51 +00:00
|
|
|
TRACE("returning %S\n", buffer);
|
2005-03-15 19:40:22 +00:00
|
|
|
return unique;
|
1998-12-04 18:28:13 +00:00
|
|
|
}
|
|
|
|
|
1999-05-19 17:57:02 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-30 11:42:05 +00:00
|
|
|
BOOL WINAPI
|
2001-07-19 18:42:02 +00:00
|
|
|
GetFileTime(HANDLE hFile,
|
|
|
|
LPFILETIME lpCreationTime,
|
|
|
|
LPFILETIME lpLastAccessTime,
|
|
|
|
LPFILETIME lpLastWriteTime)
|
1998-12-04 18:28:13 +00:00
|
|
|
{
|
1999-04-14 00:52:19 +00:00
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
FILE_BASIC_INFORMATION FileBasic;
|
2001-07-19 18:42:02 +00:00
|
|
|
NTSTATUS Status;
|
2000-10-01 19:54:57 +00:00
|
|
|
|
2004-05-28 13:17:32 +00:00
|
|
|
if(IsConsoleHandle(hFile))
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2001-07-19 18:42:02 +00:00
|
|
|
Status = NtQueryInformationFile(hFile,
|
|
|
|
&IoStatusBlock,
|
|
|
|
&FileBasic,
|
|
|
|
sizeof(FILE_BASIC_INFORMATION),
|
|
|
|
FileBasicInformation);
|
|
|
|
if (!NT_SUCCESS(Status))
|
1999-04-14 00:52:19 +00:00
|
|
|
{
|
2001-07-19 18:42:02 +00:00
|
|
|
SetLastErrorByStatus(Status);
|
1999-04-14 00:52:19 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
1999-05-19 17:57:02 +00:00
|
|
|
|
2001-07-19 18:42:02 +00:00
|
|
|
if (lpCreationTime)
|
|
|
|
memcpy(lpCreationTime, &FileBasic.CreationTime, sizeof(FILETIME));
|
|
|
|
if (lpLastAccessTime)
|
|
|
|
memcpy(lpLastAccessTime, &FileBasic.LastAccessTime, sizeof(FILETIME));
|
|
|
|
if (lpLastWriteTime)
|
|
|
|
memcpy(lpLastWriteTime, &FileBasic.LastWriteTime, sizeof(FILETIME));
|
1999-05-19 17:57:02 +00:00
|
|
|
|
1999-04-14 00:52:19 +00:00
|
|
|
return TRUE;
|
1998-12-04 18:28:13 +00:00
|
|
|
}
|
|
|
|
|
1999-05-19 17:57:02 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-30 11:42:05 +00:00
|
|
|
BOOL WINAPI
|
2001-07-19 18:42:02 +00:00
|
|
|
SetFileTime(HANDLE hFile,
|
|
|
|
CONST FILETIME *lpCreationTime,
|
|
|
|
CONST FILETIME *lpLastAccessTime,
|
|
|
|
CONST FILETIME *lpLastWriteTime)
|
1998-12-04 18:28:13 +00:00
|
|
|
{
|
1999-04-14 00:52:19 +00:00
|
|
|
FILE_BASIC_INFORMATION FileBasic;
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
2001-07-19 18:42:02 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
|
2004-05-28 13:17:32 +00:00
|
|
|
if(IsConsoleHandle(hFile))
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2001-07-19 18:42:02 +00:00
|
|
|
Status = NtQueryInformationFile(hFile,
|
|
|
|
&IoStatusBlock,
|
|
|
|
&FileBasic,
|
|
|
|
sizeof(FILE_BASIC_INFORMATION),
|
|
|
|
FileBasicInformation);
|
|
|
|
if (!NT_SUCCESS(Status))
|
1999-04-14 00:52:19 +00:00
|
|
|
{
|
2001-07-19 18:42:02 +00:00
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lpCreationTime)
|
|
|
|
memcpy(&FileBasic.CreationTime, lpCreationTime, sizeof(FILETIME));
|
|
|
|
if (lpLastAccessTime)
|
|
|
|
memcpy(&FileBasic.LastAccessTime, lpLastAccessTime, sizeof(FILETIME));
|
|
|
|
if (lpLastWriteTime)
|
|
|
|
memcpy(&FileBasic.LastWriteTime, lpLastWriteTime, sizeof(FILETIME));
|
|
|
|
|
|
|
|
// should i initialize changetime ???
|
|
|
|
|
|
|
|
Status = NtSetInformationFile(hFile,
|
|
|
|
&IoStatusBlock,
|
|
|
|
&FileBasic,
|
|
|
|
sizeof(FILE_BASIC_INFORMATION),
|
|
|
|
FileBasicInformation);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(Status);
|
1999-04-14 00:52:19 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
1999-04-14 00:52:19 +00:00
|
|
|
return TRUE;
|
1998-12-08 16:51:47 +00:00
|
|
|
}
|
1999-01-16 02:11:45 +00:00
|
|
|
|
1999-05-19 17:57:02 +00:00
|
|
|
|
2002-11-07 02:52:37 +00:00
|
|
|
/*
|
2003-07-10 18:50:51 +00:00
|
|
|
* The caller must have opened the file with the DesiredAccess FILE_WRITE_DATA flag set.
|
|
|
|
*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-30 11:42:05 +00:00
|
|
|
BOOL WINAPI
|
2001-07-19 18:42:02 +00:00
|
|
|
SetEndOfFile(HANDLE hFile)
|
1999-01-16 02:11:45 +00:00
|
|
|
{
|
2002-11-07 02:52:37 +00:00
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
FILE_END_OF_FILE_INFORMATION EndOfFileInfo;
|
|
|
|
FILE_ALLOCATION_INFORMATION FileAllocationInfo;
|
|
|
|
FILE_POSITION_INFORMATION FilePosInfo;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
2004-05-28 13:17:32 +00:00
|
|
|
if(IsConsoleHandle(hFile))
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2002-11-07 02:52:37 +00:00
|
|
|
//get current position
|
|
|
|
Status = NtQueryInformationFile(
|
|
|
|
hFile,
|
|
|
|
&IoStatusBlock,
|
|
|
|
&FilePosInfo,
|
|
|
|
sizeof(FILE_POSITION_INFORMATION),
|
|
|
|
FilePositionInformation
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status)){
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EndOfFileInfo.EndOfFile.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
|
|
|
|
|
|
|
|
/*
|
2005-05-09 01:46:57 +00:00
|
|
|
NOTE:
|
2002-11-07 02:52:37 +00:00
|
|
|
This call is not supposed to free up any space after the eof marker
|
|
|
|
if the file gets truncated. We have to deallocate the space explicitly afterwards.
|
2005-05-09 01:46:57 +00:00
|
|
|
But...most file systems dispatch both FileEndOfFileInformation
|
2002-11-07 02:52:37 +00:00
|
|
|
and FileAllocationInformation as they were the same command.
|
|
|
|
|
|
|
|
*/
|
|
|
|
Status = NtSetInformationFile(
|
|
|
|
hFile,
|
|
|
|
&IoStatusBlock, //out
|
|
|
|
&EndOfFileInfo,
|
|
|
|
sizeof(FILE_END_OF_FILE_INFORMATION),
|
|
|
|
FileEndOfFileInformation
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status)){
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
FileAllocationInfo.AllocationSize.QuadPart = FilePosInfo.CurrentByteOffset.QuadPart;
|
|
|
|
|
|
|
|
|
|
|
|
Status = NtSetInformationFile(
|
|
|
|
hFile,
|
|
|
|
&IoStatusBlock, //out
|
|
|
|
&FileAllocationInfo,
|
|
|
|
sizeof(FILE_ALLOCATION_INFORMATION),
|
|
|
|
FileAllocationInformation
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status)){
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2002-11-07 02:52:37 +00:00
|
|
|
return TRUE;
|
|
|
|
|
1999-01-16 02:11:45 +00:00
|
|
|
}
|
2000-03-15 18:30:30 +00:00
|
|
|
|
2004-03-18 16:19:26 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
BOOL
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2004-03-18 16:19:26 +00:00
|
|
|
SetFileValidData(
|
|
|
|
HANDLE hFile,
|
|
|
|
LONGLONG ValidDataLength
|
|
|
|
)
|
|
|
|
{
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
FILE_VALID_DATA_LENGTH_INFORMATION ValidDataLengthInformation;
|
|
|
|
NTSTATUS Status;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-03-18 16:19:26 +00:00
|
|
|
ValidDataLengthInformation.ValidDataLength.QuadPart = ValidDataLength;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-03-18 16:19:26 +00:00
|
|
|
Status = NtSetInformationFile(
|
|
|
|
hFile,
|
|
|
|
&IoStatusBlock, //out
|
|
|
|
&ValidDataLengthInformation,
|
|
|
|
sizeof(FILE_VALID_DATA_LENGTH_INFORMATION),
|
|
|
|
FileValidDataLengthInformation
|
|
|
|
);
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-03-18 16:19:26 +00:00
|
|
|
if (!NT_SUCCESS(Status)){
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-03-18 16:19:26 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2004-03-18 18:29:19 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
|
2004-03-18 18:29:19 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
BOOL
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2004-03-18 18:29:19 +00:00
|
|
|
SetFileShortNameW(
|
|
|
|
HANDLE hFile,
|
|
|
|
LPCWSTR lpShortName)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
ULONG NeededSize;
|
|
|
|
UNICODE_STRING ShortName;
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
2006-01-21 22:36:37 +00:00
|
|
|
PFILE_NAME_INFORMATION FileNameInfo;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-05-28 13:17:32 +00:00
|
|
|
if(IsConsoleHandle(hFile))
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-03-18 18:29:19 +00:00
|
|
|
if(!lpShortName)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-03-18 18:29:19 +00:00
|
|
|
RtlInitUnicodeString(&ShortName, lpShortName);
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-03-18 18:29:19 +00:00
|
|
|
NeededSize = sizeof(FILE_NAME_INFORMATION) + ShortName.Length + sizeof(WCHAR);
|
2006-01-21 22:36:37 +00:00
|
|
|
if(!(FileNameInfo = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, NeededSize)))
|
2004-03-18 18:29:19 +00:00
|
|
|
{
|
|
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2006-01-21 22:36:37 +00:00
|
|
|
FileNameInfo->FileNameLength = ShortName.Length;
|
|
|
|
RtlCopyMemory(FileNameInfo->FileName, ShortName.Buffer, ShortName.Length);
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-03-18 18:29:19 +00:00
|
|
|
Status = NtSetInformationFile(hFile,
|
|
|
|
&IoStatusBlock, //out
|
2006-01-21 22:36:37 +00:00
|
|
|
FileNameInfo,
|
2004-03-18 18:29:19 +00:00
|
|
|
NeededSize,
|
|
|
|
FileShortNameInformation);
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2006-01-21 22:36:37 +00:00
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameInfo);
|
2004-03-18 18:29:19 +00:00
|
|
|
if(!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(Status);
|
2006-01-21 22:36:37 +00:00
|
|
|
return FALSE;
|
2004-03-18 18:29:19 +00:00
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2006-01-21 22:36:37 +00:00
|
|
|
return TRUE;
|
2004-03-18 18:29:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
BOOL
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2004-03-18 18:29:19 +00:00
|
|
|
SetFileShortNameA(
|
|
|
|
HANDLE hFile,
|
|
|
|
LPCSTR lpShortName
|
|
|
|
)
|
|
|
|
{
|
2005-03-15 19:40:22 +00:00
|
|
|
PWCHAR ShortNameW;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-05-28 13:17:32 +00:00
|
|
|
if(IsConsoleHandle(hFile))
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2004-03-18 18:29:19 +00:00
|
|
|
if(!lpShortName)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-03-15 19:40:22 +00:00
|
|
|
if (!(ShortNameW = FilenameA2W(lpShortName, FALSE)))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return SetFileShortNameW(hFile, ShortNameW);
|
2004-03-18 18:29:19 +00:00
|
|
|
}
|
|
|
|
|
2004-09-22 09:31:01 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
BOOL
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2004-09-22 09:31:01 +00:00
|
|
|
CheckNameLegalDOS8Dot3W(
|
|
|
|
LPCWSTR lpName,
|
|
|
|
LPSTR lpOemName OPTIONAL,
|
|
|
|
DWORD OemNameSize OPTIONAL,
|
|
|
|
PBOOL pbNameContainsSpaces OPTIONAL,
|
|
|
|
PBOOL pbNameLegal
|
|
|
|
)
|
|
|
|
{
|
|
|
|
UNICODE_STRING Name;
|
|
|
|
ANSI_STRING AnsiName;
|
|
|
|
|
|
|
|
if(lpName == NULL ||
|
|
|
|
(lpOemName == NULL && OemNameSize != 0) ||
|
|
|
|
pbNameLegal == NULL)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(lpOemName != NULL)
|
|
|
|
{
|
|
|
|
AnsiName.Buffer = lpOemName;
|
2007-01-26 07:22:19 +00:00
|
|
|
AnsiName.MaximumLength = (USHORT)OemNameSize * sizeof(CHAR);
|
2004-09-22 09:31:01 +00:00
|
|
|
AnsiName.Length = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlInitUnicodeString(&Name, lpName);
|
|
|
|
|
|
|
|
*pbNameLegal = RtlIsNameLegalDOS8Dot3(&Name,
|
|
|
|
(lpOemName ? &AnsiName : NULL),
|
|
|
|
(BOOLEAN*)pbNameContainsSpaces);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
BOOL
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2004-09-22 09:31:01 +00:00
|
|
|
CheckNameLegalDOS8Dot3A(
|
|
|
|
LPCSTR lpName,
|
|
|
|
LPSTR lpOemName OPTIONAL,
|
|
|
|
DWORD OemNameSize OPTIONAL,
|
|
|
|
PBOOL pbNameContainsSpaces OPTIONAL,
|
|
|
|
PBOOL pbNameLegal
|
|
|
|
)
|
|
|
|
{
|
|
|
|
UNICODE_STRING Name;
|
|
|
|
ANSI_STRING AnsiName, AnsiInputName;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
if(lpName == NULL ||
|
|
|
|
(lpOemName == NULL && OemNameSize != 0) ||
|
|
|
|
pbNameLegal == NULL)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(lpOemName != NULL)
|
|
|
|
{
|
|
|
|
AnsiName.Buffer = lpOemName;
|
2007-01-26 07:22:19 +00:00
|
|
|
AnsiName.MaximumLength = (USHORT)OemNameSize * sizeof(CHAR);
|
2004-09-22 09:31:01 +00:00
|
|
|
AnsiName.Length = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlInitAnsiString(&AnsiInputName, (LPSTR)lpName);
|
|
|
|
if(bIsFileApiAnsi)
|
|
|
|
Status = RtlAnsiStringToUnicodeString(&Name, &AnsiInputName, TRUE);
|
|
|
|
else
|
|
|
|
Status = RtlOemStringToUnicodeString(&Name, &AnsiInputName, TRUE);
|
|
|
|
|
|
|
|
if(!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastErrorByStatus(Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
*pbNameLegal = RtlIsNameLegalDOS8Dot3(&Name,
|
|
|
|
(lpOemName ? &AnsiName : NULL),
|
|
|
|
(BOOLEAN*)pbNameContainsSpaces);
|
|
|
|
|
2004-10-31 01:36:37 +00:00
|
|
|
RtlFreeUnicodeString(&Name);
|
|
|
|
|
2004-09-22 09:31:01 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2006-01-14 13:37:08 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
DWORD
|
|
|
|
WINAPI
|
|
|
|
GetFinalPathNameByHandleA(IN HANDLE hFile,
|
|
|
|
OUT LPSTR lpszFilePath,
|
|
|
|
IN DWORD cchFilePath,
|
|
|
|
IN DWORD dwFlags)
|
|
|
|
{
|
|
|
|
WCHAR FilePathW[MAX_PATH];
|
|
|
|
UNICODE_STRING FilePathU;
|
|
|
|
DWORD PrevLastError;
|
|
|
|
DWORD Ret = 0;
|
|
|
|
|
|
|
|
if (cchFilePath != 0 &&
|
|
|
|
cchFilePath > sizeof(FilePathW) / sizeof(FilePathW[0]))
|
|
|
|
{
|
|
|
|
FilePathU.Length = 0;
|
2007-01-26 07:22:19 +00:00
|
|
|
FilePathU.MaximumLength = (USHORT)cchFilePath * sizeof(WCHAR);
|
2006-01-14 13:37:08 +00:00
|
|
|
FilePathU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
|
|
0,
|
|
|
|
FilePathU.MaximumLength);
|
|
|
|
if (FilePathU.Buffer == NULL)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FilePathU.Length = 0;
|
|
|
|
FilePathU.MaximumLength = sizeof(FilePathW);
|
|
|
|
FilePathU.Buffer = FilePathW;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* save the last error code */
|
|
|
|
PrevLastError = GetLastError();
|
|
|
|
SetLastError(ERROR_SUCCESS);
|
|
|
|
|
|
|
|
/* call the unicode version that does all the work */
|
|
|
|
Ret = GetFinalPathNameByHandleW(hFile,
|
|
|
|
FilePathU.Buffer,
|
|
|
|
cchFilePath,
|
|
|
|
dwFlags);
|
|
|
|
|
|
|
|
if (GetLastError() == ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
/* no error, restore the last error code and convert the string */
|
|
|
|
SetLastError(PrevLastError);
|
|
|
|
|
|
|
|
Ret = FilenameU2A_FitOrFail(lpszFilePath,
|
|
|
|
cchFilePath,
|
|
|
|
&FilePathU);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* free allocated memory if necessary */
|
|
|
|
if (FilePathU.Buffer != FilePathW)
|
|
|
|
{
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(),
|
|
|
|
0,
|
|
|
|
FilePathU.Buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
|
|
|
DWORD
|
|
|
|
WINAPI
|
|
|
|
GetFinalPathNameByHandleW(IN HANDLE hFile,
|
|
|
|
OUT LPWSTR lpszFilePath,
|
|
|
|
IN DWORD cchFilePath,
|
|
|
|
IN DWORD dwFlags)
|
|
|
|
{
|
2006-01-14 22:25:20 +00:00
|
|
|
if (dwFlags & ~(VOLUME_NAME_DOS | VOLUME_NAME_GUID | VOLUME_NAME_NT |
|
|
|
|
VOLUME_NAME_NONE | FILE_NAME_NORMALIZED | FILE_NAME_OPENED))
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-01-14 13:37:08 +00:00
|
|
|
UNIMPLEMENTED;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-01-14 22:25:20 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
|
|
|
BOOL
|
|
|
|
WINAPI
|
|
|
|
SetFileBandwidthReservation(IN HANDLE hFile,
|
|
|
|
IN DWORD nPeriodMilliseconds,
|
|
|
|
IN DWORD nBytesPerPeriod,
|
|
|
|
IN BOOL bDiscardable,
|
|
|
|
OUT LPDWORD lpTransferSize,
|
|
|
|
OUT LPDWORD lpNumOutstandingRequests)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
|
|
|
BOOL
|
|
|
|
WINAPI
|
|
|
|
GetFileBandwidthReservation(IN HANDLE hFile,
|
|
|
|
OUT LPDWORD lpPeriodMilliseconds,
|
|
|
|
OUT LPDWORD lpBytesPerPeriod,
|
|
|
|
OUT LPBOOL pDiscardable,
|
|
|
|
OUT LPDWORD lpTransferSize,
|
|
|
|
OUT LPDWORD lpNumOutstandingRequests)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
|
|
|
BOOL
|
|
|
|
WINAPI
|
|
|
|
SetFileCompletionNotificationModes(IN HANDLE FileHandle,
|
|
|
|
IN UCHAR Flags)
|
|
|
|
{
|
|
|
|
if (Flags & ~(FILE_SKIP_COMPLETION_PORT_ON_SUCCESS | FILE_SKIP_SET_EVENT_ON_HANDLE))
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
|
|
|
HANDLE
|
|
|
|
WINAPI
|
|
|
|
OpenFileById(IN HANDLE hFile,
|
|
|
|
IN LPFILE_ID_DESCRIPTOR lpFileID,
|
|
|
|
IN DWORD dwDesiredAccess,
|
|
|
|
IN DWORD dwShareMode,
|
|
|
|
IN LPSECURITY_ATTRIBUTES lpSecurityAttributes OPTIONAL,
|
|
|
|
IN DWORD dwFlags)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return INVALID_HANDLE_VALUE;
|
|
|
|
}
|
|
|
|
|
2008-12-27 17:24:07 +00:00
|
|
|
/*
|
|
|
|
* @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
|
|
|
|
)
|
|
|
|
{
|
2009-12-03 18:41:53 +00:00
|
|
|
HANDLE hReplaced = NULL, hReplacement = NULL;
|
2010-05-29 12:31:48 +00:00
|
|
|
UNICODE_STRING NtReplacedName = { 0, 0, NULL };
|
|
|
|
UNICODE_STRING NtReplacementName = { 0, 0, NULL };
|
2008-12-27 17:24:07 +00:00
|
|
|
DWORD Error = ERROR_SUCCESS;
|
|
|
|
NTSTATUS Status;
|
|
|
|
BOOL Ret = FALSE;
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
2009-12-03 18:41:53 +00:00
|
|
|
PVOID Buffer = NULL ;
|
2008-12-27 17:24:07 +00:00
|
|
|
|
|
|
|
if (dwReplaceFlags)
|
|
|
|
FIXME("Ignoring flags %x\n", dwReplaceFlags);
|
|
|
|
|
|
|
|
/* First two arguments are mandatory */
|
|
|
|
if (!lpReplacedFileName || !lpReplacementFileName)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2009-12-03 18:41:53 +00:00
|
|
|
/* Back it up */
|
|
|
|
if(lpBackupFileName)
|
|
|
|
{
|
|
|
|
if(!CopyFileW(lpReplacedFileName, lpBackupFileName, FALSE))
|
|
|
|
{
|
|
|
|
Error = GetLastError();
|
|
|
|
goto Cleanup ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-27 17:24:07 +00:00
|
|
|
/* 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,
|
2009-12-03 18:41:53 +00:00
|
|
|
GENERIC_READ | GENERIC_WRITE | DELETE | SYNCHRONIZE | WRITE_DAC,
|
2008-12-27 17:24:07 +00:00
|
|
|
&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;
|
|
|
|
}
|
|
|
|
|
2009-12-03 18:41:53 +00:00
|
|
|
/* Blank it */
|
|
|
|
SetEndOfFile(hReplaced) ;
|
|
|
|
|
2008-12-27 17:24:07 +00:00
|
|
|
/*
|
|
|
|
* Open the replacement file for reading, writing, and deleting
|
2009-12-03 18:41:53 +00:00
|
|
|
* (deleting is needed when finished)
|
2008-12-27 17:24:07 +00:00
|
|
|
*/
|
|
|
|
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,
|
2009-12-03 18:41:53 +00:00
|
|
|
GENERIC_READ | DELETE | SYNCHRONIZE,
|
2008-12-27 17:24:07 +00:00
|
|
|
&ObjectAttributes,
|
|
|
|
&IoStatusBlock,
|
|
|
|
0,
|
2009-12-03 18:41:53 +00:00
|
|
|
FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE);
|
2008-12-27 17:24:07 +00:00
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
Error = RtlNtStatusToDosError(Status);
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
2009-12-03 18:41:53 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-27 17:24:07 +00:00
|
|
|
Ret = TRUE;
|
|
|
|
|
|
|
|
/* Perform resource cleanup */
|
|
|
|
Cleanup:
|
|
|
|
if (hReplaced) NtClose(hReplaced);
|
|
|
|
if (hReplacement) NtClose(hReplacement);
|
2009-12-03 18:41:53 +00:00
|
|
|
if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
|
2008-12-27 17:24:07 +00:00
|
|
|
|
2010-05-29 12:31:48 +00:00
|
|
|
if (NtReplacementName.Buffer)
|
|
|
|
RtlFreeHeap(GetProcessHeap(), 0, NtReplacementName.Buffer);
|
|
|
|
if (NtReplacedName.Buffer)
|
|
|
|
RtlFreeHeap(GetProcessHeap(), 0, NtReplacedName.Buffer);
|
2008-12-27 17:24:07 +00:00
|
|
|
|
|
|
|
/* If there was an error, set the error code */
|
|
|
|
if(!Ret)
|
|
|
|
{
|
|
|
|
TRACE("ReplaceFileW failed (error=%d)\n", Error);
|
|
|
|
SetLastError(Error);
|
|
|
|
}
|
|
|
|
return Ret;
|
|
|
|
}
|
|
|
|
|
2000-03-15 18:30:30 +00:00
|
|
|
/* EOF */
|