mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-29 12:23:30 +00:00
[KERNEL32]: Implement Wow64Enable/Disable/RevertWow64Direction, document the Rtl equivalents in NDK, export and implement them in NTDLL.
[KERNEL32]: Cleanup files a bit.
- Bintype.c is gone and moved into VDM (these are functions for VDM support).
- Npipe.c and pipe.c are merged.
- Dosdev is moved into client, these are not quite File APIs.
- Base(8Bit/Unicode) APIs are moved into utils.c
- Wow64 APIs are moved into utils.c
- The mess that was file.c has the Replace* file APIs going into move.c (similar behaviors), the Open* APIs into create.c (similar) and the Read/Write Scatter/Gather APIs into rw.c (where they belong). What remained in file.c were mostly Set/Query functions, so it becomes fileinfo.c
- The remaining APIs in file.c were all about paths -- at the file level, specifically filenames, so they go into filename.c
- Move some File API functions from certain files into other files where they belong more.
svn path=/trunk/; revision=54326
This commit is contained in:
@@ -972,8 +972,8 @@
|
||||
@ stdcall -arch=x86_64 RtlVirtualUnwind(long long long ptr ptr ptr ptr ptr)
|
||||
@ stdcall RtlWalkFrameChain(ptr long long)
|
||||
@ stdcall RtlWalkHeap(long ptr)
|
||||
//@ stdcall RtlWow64EnableFsRedirection(long)
|
||||
//@ stdcall RtlWow64EnableFsRedirectionEx(long ptr)
|
||||
@ stdcall RtlWow64EnableFsRedirection(long)
|
||||
@ stdcall RtlWow64EnableFsRedirectionEx(long ptr)
|
||||
@ stdcall RtlWakeAllConditionVariable(ptr)
|
||||
@ stdcall RtlWakeConditionVariable(ptr)
|
||||
//@ stdcall RtlWriteMemoryStream
|
||||
|
||||
@@ -972,8 +972,8 @@
|
||||
@ stdcall -arch=x86_64 RtlVirtualUnwind(long long long ptr ptr ptr ptr ptr)
|
||||
@ stdcall RtlWalkFrameChain(ptr long long)
|
||||
@ stdcall RtlWalkHeap(long ptr)
|
||||
;@ stdcall RtlWow64EnableFsRedirection(long)
|
||||
;@ stdcall RtlWow64EnableFsRedirectionEx(long ptr)
|
||||
@ stdcall RtlWow64EnableFsRedirection(long)
|
||||
@ stdcall RtlWow64EnableFsRedirectionEx(long ptr)
|
||||
@ stdcall RtlWakeAllConditionVariable(ptr)
|
||||
@ stdcall RtlWakeConditionVariable(ptr)
|
||||
;@ stdcall RtlWriteMemoryStream
|
||||
|
||||
@@ -536,3 +536,30 @@ RtlDosApplyFileIsolationRedirection_Ustr(IN ULONG Flags,
|
||||
{
|
||||
return STATUS_SXS_KEY_NOT_FOUND;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSYSAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RtlWow64EnableFsRedirection(IN BOOLEAN Wow64FsEnableRedirection)
|
||||
{
|
||||
/* This is what Windows returns on x86 */
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSYSAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RtlWow64EnableFsRedirectionEx(IN PVOID Wow64FsEnableRedirection,
|
||||
OUT PVOID *OldFsRedirectionLevel)
|
||||
{
|
||||
/* This is what Windows returns on x86 */
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
||||
@@ -12,6 +12,7 @@ list(APPEND SOURCE
|
||||
client/atom.c
|
||||
client/compname.c
|
||||
client/debugger.c
|
||||
client/dosdev.c
|
||||
client/dllmain.c
|
||||
client/environ.c
|
||||
client/except.c
|
||||
@@ -38,7 +39,6 @@ list(APPEND SOURCE
|
||||
client/virtmem.c
|
||||
client/vista.c
|
||||
client/file/backup.c
|
||||
client/file/bintype.c
|
||||
client/file/cnotify.c
|
||||
client/file/copy.c
|
||||
client/file/console.c
|
||||
@@ -46,9 +46,9 @@ list(APPEND SOURCE
|
||||
client/file/delete.c
|
||||
client/file/deviceio.c
|
||||
client/file/dir.c
|
||||
client/file/dosdev.c
|
||||
client/file/file.c
|
||||
client/file/fileinfo.c
|
||||
client/file/filemap.c
|
||||
client/file/filename.c
|
||||
client/file/find.c
|
||||
client/file/hardlink.c
|
||||
client/file/iocompl.c
|
||||
@@ -57,7 +57,6 @@ list(APPEND SOURCE
|
||||
client/file/mailslot.c
|
||||
client/file/move.c
|
||||
client/file/npipe.c
|
||||
client/file/pipe.c
|
||||
client/file/rw.c
|
||||
client/file/tape.c
|
||||
client/file/volume.c
|
||||
|
||||
@@ -1,343 +0,0 @@
|
||||
/* $Id$
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: lib/kernel32/file/bintype.c
|
||||
* PURPOSE: Binary detection functions
|
||||
* PROGRAMMER: Alexandre Julliard (WINE)
|
||||
* Thomas Weidenmueller (w3seek@users.sourceforge.net)
|
||||
* UPDATE HISTORY:
|
||||
* 02/05/2004 - Ported/Adapted from WINE
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <k32.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#if DBG
|
||||
DEBUG_CHANNEL(kernel32file);
|
||||
#endif
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
/* Check whether a file is an OS/2 or a very old Windows executable
|
||||
* by testing on import of KERNEL.
|
||||
*
|
||||
* FIXME: is reading the module imports the only way of discerning
|
||||
* old Windows binaries from OS/2 ones ? At least it seems so...
|
||||
*/
|
||||
static DWORD WINAPI
|
||||
InternalIsOS2OrOldWin(HANDLE hFile, IMAGE_DOS_HEADER *mz, IMAGE_OS2_HEADER *ne)
|
||||
{
|
||||
DWORD CurPos;
|
||||
LPWORD modtab = NULL;
|
||||
LPSTR nametab = NULL;
|
||||
DWORD Read, Ret;
|
||||
int i;
|
||||
|
||||
Ret = BINARY_OS216;
|
||||
CurPos = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
|
||||
|
||||
/* read modref table */
|
||||
if((SetFilePointer(hFile, mz->e_lfanew + ne->ne_modtab, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) ||
|
||||
(!(modtab = HeapAlloc(GetProcessHeap(), 0, ne->ne_cmod * sizeof(WORD)))) ||
|
||||
(!(ReadFile(hFile, modtab, ne->ne_cmod * sizeof(WORD), &Read, NULL))) ||
|
||||
(Read != (DWORD)ne->ne_cmod * sizeof(WORD)))
|
||||
{
|
||||
goto broken;
|
||||
}
|
||||
|
||||
/* read imported names table */
|
||||
if((SetFilePointer(hFile, mz->e_lfanew + ne->ne_imptab, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) ||
|
||||
(!(nametab = HeapAlloc(GetProcessHeap(), 0, ne->ne_enttab - ne->ne_imptab))) ||
|
||||
(!(ReadFile(hFile, nametab, ne->ne_enttab - ne->ne_imptab, &Read, NULL))) ||
|
||||
(Read != (DWORD)ne->ne_enttab - ne->ne_imptab))
|
||||
{
|
||||
goto broken;
|
||||
}
|
||||
|
||||
for(i = 0; i < ne->ne_cmod; i++)
|
||||
{
|
||||
LPSTR module;
|
||||
module = &nametab[modtab[i]];
|
||||
if(!strncmp(&module[1], "KERNEL", module[0]))
|
||||
{
|
||||
/* very old windows file */
|
||||
Ret = BINARY_WIN16;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
broken:
|
||||
WARN("InternalIsOS2OrOldWin(): Binary file seems to be broken\n");
|
||||
|
||||
done:
|
||||
HeapFree(GetProcessHeap(), 0, modtab);
|
||||
HeapFree(GetProcessHeap(), 0, nametab);
|
||||
SetFilePointer(hFile, CurPos, NULL, FILE_BEGIN);
|
||||
return Ret;
|
||||
}
|
||||
|
||||
static DWORD WINAPI
|
||||
InternalGetBinaryType(HANDLE hFile)
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned char magic[4];
|
||||
unsigned char ignored[12];
|
||||
unsigned short type;
|
||||
} elf;
|
||||
struct
|
||||
{
|
||||
unsigned long magic;
|
||||
unsigned long cputype;
|
||||
unsigned long cpusubtype;
|
||||
unsigned long filetype;
|
||||
} macho;
|
||||
IMAGE_DOS_HEADER mz;
|
||||
} Header;
|
||||
char magic[4];
|
||||
DWORD Read;
|
||||
|
||||
if((SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) ||
|
||||
(!ReadFile(hFile, &Header, sizeof(Header), &Read, NULL) ||
|
||||
(Read != sizeof(Header))))
|
||||
{
|
||||
return BINARY_UNKNOWN;
|
||||
}
|
||||
|
||||
if(!memcmp(Header.elf.magic, "\177ELF", sizeof(Header.elf.magic)))
|
||||
{
|
||||
/* FIXME: we don't bother to check byte order, architecture, etc. */
|
||||
switch(Header.elf.type)
|
||||
{
|
||||
case 2:
|
||||
return BINARY_UNIX_EXE;
|
||||
case 3:
|
||||
return BINARY_UNIX_LIB;
|
||||
}
|
||||
return BINARY_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Mach-o File with Endian set to Big Endian or Little Endian*/
|
||||
if(Header.macho.magic == 0xFEEDFACE ||
|
||||
Header.macho.magic == 0xCEFAEDFE)
|
||||
{
|
||||
switch(Header.macho.filetype)
|
||||
{
|
||||
case 0x8:
|
||||
/* MH_BUNDLE */
|
||||
return BINARY_UNIX_LIB;
|
||||
}
|
||||
return BINARY_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Not ELF, try DOS */
|
||||
if(Header.mz.e_magic == IMAGE_DOS_SIGNATURE)
|
||||
{
|
||||
/* We do have a DOS image so we will now try to seek into
|
||||
* the file by the amount indicated by the field
|
||||
* "Offset to extended header" and read in the
|
||||
* "magic" field information at that location.
|
||||
* This will tell us if there is more header information
|
||||
* to read or not.
|
||||
*/
|
||||
if((SetFilePointer(hFile, Header.mz.e_lfanew, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) ||
|
||||
(!ReadFile(hFile, magic, sizeof(magic), &Read, NULL) ||
|
||||
(Read != sizeof(magic))))
|
||||
{
|
||||
return BINARY_DOS;
|
||||
}
|
||||
|
||||
/* Reading the magic field succeeded so
|
||||
* we will try to determine what type it is.
|
||||
*/
|
||||
if(!memcmp(magic, "PE\0\0", sizeof(magic)))
|
||||
{
|
||||
IMAGE_FILE_HEADER FileHeader;
|
||||
if(!ReadFile(hFile, &FileHeader, sizeof(IMAGE_FILE_HEADER), &Read, NULL) ||
|
||||
(Read != sizeof(IMAGE_FILE_HEADER)))
|
||||
{
|
||||
return BINARY_DOS;
|
||||
}
|
||||
|
||||
/* FIXME - detect 32/64 bit */
|
||||
|
||||
if(FileHeader.Characteristics & IMAGE_FILE_DLL)
|
||||
return BINARY_PE_DLL32;
|
||||
return BINARY_PE_EXE32;
|
||||
}
|
||||
|
||||
if(!memcmp(magic, "NE", 1))
|
||||
{
|
||||
/* This is a Windows executable (NE) header. This can
|
||||
* mean either a 16-bit OS/2 or a 16-bit Windows or even a
|
||||
* DOS program (running under a DOS extender). To decide
|
||||
* which, we'll have to read the NE header.
|
||||
*/
|
||||
IMAGE_OS2_HEADER ne;
|
||||
if((SetFilePointer(hFile, Header.mz.e_lfanew, NULL, FILE_BEGIN) == 1) ||
|
||||
!ReadFile(hFile, &ne, sizeof(IMAGE_OS2_HEADER), &Read, NULL) ||
|
||||
(Read != sizeof(IMAGE_OS2_HEADER)))
|
||||
{
|
||||
/* Couldn't read header, so abort. */
|
||||
return BINARY_DOS;
|
||||
}
|
||||
|
||||
switch(ne.ne_exetyp)
|
||||
{
|
||||
case 2:
|
||||
return BINARY_WIN16;
|
||||
case 5:
|
||||
return BINARY_DOS;
|
||||
default:
|
||||
return InternalIsOS2OrOldWin(hFile, &Header.mz, &ne);
|
||||
}
|
||||
}
|
||||
return BINARY_DOS;
|
||||
}
|
||||
return BINARY_UNKNOWN;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
GetBinaryTypeW (
|
||||
LPCWSTR lpApplicationName,
|
||||
LPDWORD lpBinaryType
|
||||
)
|
||||
{
|
||||
HANDLE hFile;
|
||||
DWORD BinType;
|
||||
|
||||
if(!lpApplicationName || !lpBinaryType)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hFile = CreateFileW(lpApplicationName, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||
OPEN_EXISTING, 0, 0);
|
||||
if(hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BinType = InternalGetBinaryType(hFile);
|
||||
CloseHandle(hFile);
|
||||
|
||||
switch(BinType)
|
||||
{
|
||||
case BINARY_UNKNOWN:
|
||||
{
|
||||
WCHAR *dot;
|
||||
|
||||
/*
|
||||
* guess from filename
|
||||
*/
|
||||
if(!(dot = wcsrchr(lpApplicationName, L'.')))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if(!lstrcmpiW(dot, L".COM"))
|
||||
{
|
||||
*lpBinaryType = SCS_DOS_BINARY;
|
||||
return TRUE;
|
||||
}
|
||||
if(!lstrcmpiW(dot, L".PIF"))
|
||||
{
|
||||
*lpBinaryType = SCS_PIF_BINARY;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
case BINARY_PE_EXE32:
|
||||
case BINARY_PE_DLL32:
|
||||
{
|
||||
*lpBinaryType = SCS_32BIT_BINARY;
|
||||
return TRUE;
|
||||
}
|
||||
case BINARY_PE_EXE64:
|
||||
case BINARY_PE_DLL64:
|
||||
{
|
||||
*lpBinaryType = SCS_64BIT_BINARY;
|
||||
return TRUE;
|
||||
}
|
||||
case BINARY_WIN16:
|
||||
{
|
||||
*lpBinaryType = SCS_WOW_BINARY;
|
||||
return TRUE;
|
||||
}
|
||||
case BINARY_OS216:
|
||||
{
|
||||
*lpBinaryType = SCS_OS216_BINARY;
|
||||
return TRUE;
|
||||
}
|
||||
case BINARY_DOS:
|
||||
{
|
||||
*lpBinaryType = SCS_DOS_BINARY;
|
||||
return TRUE;
|
||||
}
|
||||
case BINARY_UNIX_EXE:
|
||||
case BINARY_UNIX_LIB:
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
ERR("Invalid binary type returned!\n", BinType);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
GetBinaryTypeA(IN LPCSTR lpApplicationName,
|
||||
OUT LPDWORD lpBinaryType)
|
||||
{
|
||||
ANSI_STRING ApplicationNameString;
|
||||
UNICODE_STRING ApplicationNameW;
|
||||
BOOL StringAllocated = FALSE, Result;
|
||||
NTSTATUS Status;
|
||||
|
||||
RtlInitAnsiString(&ApplicationNameString, lpApplicationName);
|
||||
|
||||
if (ApplicationNameString.Length * sizeof(WCHAR) >= NtCurrentTeb()->StaticUnicodeString.MaximumLength)
|
||||
{
|
||||
StringAllocated = TRUE;
|
||||
Status = RtlAnsiStringToUnicodeString(&ApplicationNameW, &ApplicationNameString, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = RtlAnsiStringToUnicodeString(&(NtCurrentTeb()->StaticUnicodeString), &ApplicationNameString, FALSE);
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
BaseSetLastNTError(Status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (StringAllocated)
|
||||
{
|
||||
Result = GetBinaryTypeW(ApplicationNameW.Buffer, lpBinaryType);
|
||||
RtlFreeUnicodeString(&ApplicationNameW);
|
||||
}
|
||||
else
|
||||
{
|
||||
Result = GetBinaryTypeW(NtCurrentTeb()->StaticUnicodeString.Buffer, lpBinaryType);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -375,4 +375,214 @@ HANDLE WINAPI CreateFileW (LPCWSTR lpFileName,
|
||||
return FileHandle;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
HFILE WINAPI
|
||||
OpenFile(LPCSTR lpFileName,
|
||||
LPOFSTRUCT lpReOpenBuff,
|
||||
UINT uStyle)
|
||||
{
|
||||
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;
|
||||
|
||||
TRACE("OpenFile('%s', lpReOpenBuff %x, uStyle %x)\n", lpFileName, lpReOpenBuff, uStyle);
|
||||
|
||||
if (lpReOpenBuff == NULL)
|
||||
{
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
RtlInitAnsiString (&FileName, (LPSTR)lpFileName);
|
||||
|
||||
/* convert ansi (or oem) string to unicode */
|
||||
if (bIsFileApiAnsi)
|
||||
RtlAnsiStringToUnicodeString (&FileNameU, &FileName, TRUE);
|
||||
else
|
||||
RtlOemStringToUnicodeString (&FileNameU, &FileName, TRUE);
|
||||
|
||||
Len = SearchPathW (NULL,
|
||||
FileNameU.Buffer,
|
||||
NULL,
|
||||
OFS_MAXPATHNAME,
|
||||
PathNameW,
|
||||
&FilePart);
|
||||
|
||||
RtlFreeUnicodeString(&FileNameU);
|
||||
|
||||
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;
|
||||
|
||||
RtlInitUnicodeString(&FileNameU, PathNameW);
|
||||
|
||||
/* convert unicode string to ansi (or oem) */
|
||||
if (bIsFileApiAnsi)
|
||||
RtlUnicodeStringToAnsiString (&FileName, &FileNameU, FALSE);
|
||||
else
|
||||
RtlUnicodeStringToOemString (&FileName, &FileNameU, FALSE);
|
||||
|
||||
if (!RtlDosPathNameToNtPathName_U (PathNameW,
|
||||
&FileNameString,
|
||||
NULL,
|
||||
NULL))
|
||||
{
|
||||
return (HFILE)INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
// FILE_SHARE_READ
|
||||
// FILE_NO_INTERMEDIATE_BUFFERING
|
||||
|
||||
ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
|
||||
ObjectAttributes.RootDirectory = NULL;
|
||||
ObjectAttributes.ObjectName = &FileNameString;
|
||||
ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT;
|
||||
ObjectAttributes.SecurityDescriptor = NULL;
|
||||
ObjectAttributes.SecurityQualityOfService = NULL;
|
||||
|
||||
errCode = NtOpenFile (&FileHandle,
|
||||
GENERIC_READ|SYNCHRONIZE,
|
||||
&ObjectAttributes,
|
||||
&IoStatusBlock,
|
||||
FILE_SHARE_READ,
|
||||
FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT);
|
||||
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameString.Buffer);
|
||||
|
||||
lpReOpenBuff->nErrCode = RtlNtStatusToDosError(errCode);
|
||||
|
||||
if (!NT_SUCCESS(errCode))
|
||||
{
|
||||
BaseSetLastNTError (errCode);
|
||||
return (HFILE)INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if (uStyle & OF_EXIST)
|
||||
{
|
||||
NtClose(FileHandle);
|
||||
return (HFILE)1;
|
||||
}
|
||||
|
||||
return (HFILE)FileHandle;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
OpenDataFile(HANDLE hFile, DWORD dwUnused)
|
||||
{
|
||||
STUB;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
HANDLE
|
||||
WINAPI
|
||||
ReOpenFile(IN HANDLE hOriginalFile,
|
||||
IN DWORD dwDesiredAccess,
|
||||
IN DWORD dwShareMode,
|
||||
IN DWORD dwFlags)
|
||||
{
|
||||
STUB;
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
||||
@@ -242,68 +242,24 @@ DeviceIoControl(IN HANDLE hDevice,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
GetOverlappedResult(IN HANDLE hFile,
|
||||
IN LPOVERLAPPED lpOverlapped,
|
||||
OUT LPDWORD lpNumberOfBytesTransferred,
|
||||
IN BOOL bWait)
|
||||
CancelIo(IN HANDLE hFile)
|
||||
{
|
||||
DWORD WaitStatus;
|
||||
HANDLE hObject;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
NTSTATUS Status;
|
||||
|
||||
|
||||
/* Check for pending operation */
|
||||
if (lpOverlapped->Internal == STATUS_PENDING)
|
||||
Status = NtCancelIoFile(hFile, &IoStatusBlock);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Check if the caller is okay with waiting */
|
||||
if (!bWait)
|
||||
{
|
||||
/* Set timeout */
|
||||
WaitStatus = WAIT_TIMEOUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Wait for the result */
|
||||
hObject = lpOverlapped->hEvent ? lpOverlapped->hEvent : hFile;
|
||||
WaitStatus = WaitForSingleObject(hObject, INFINITE);
|
||||
}
|
||||
|
||||
|
||||
/* Check for timeout */
|
||||
if (WaitStatus == WAIT_TIMEOUT)
|
||||
{
|
||||
/* We have to override the last error with INCOMPLETE instead */
|
||||
SetLastError(ERROR_IO_INCOMPLETE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* Fail if we had an error -- the last error is already set */
|
||||
if (WaitStatus != 0) return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* Return bytes transferred */
|
||||
*lpNumberOfBytesTransferred = lpOverlapped->InternalHigh;
|
||||
|
||||
|
||||
/* Check for failure during I/O */
|
||||
if (!NT_SUCCESS(lpOverlapped->Internal))
|
||||
{
|
||||
/* Set the error and fail */
|
||||
BaseSetLastNTError(lpOverlapped->Internal);
|
||||
BaseSetLastNTError(Status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* All done */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
||||
|
||||
-1007
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,406 @@
|
||||
/* $Id: file.c 54310 2011-11-06 04:13:21Z ion $
|
||||
*
|
||||
* 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)
|
||||
* Pierre Schweitzer (pierre.schweitzer@reactos.org)
|
||||
* UPDATE HISTORY:
|
||||
* Created 01/11/98
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <k32.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* GLOBALS ******************************************************************/
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
* GetTempFileNameA (KERNEL32.@)
|
||||
*/
|
||||
UINT WINAPI
|
||||
GetTempFileNameA(IN LPCSTR lpPathName,
|
||||
IN LPCSTR lpPrefixString,
|
||||
IN UINT uUnique,
|
||||
OUT LPSTR lpTempFileName)
|
||||
{
|
||||
UINT ID;
|
||||
NTSTATUS Status;
|
||||
LPWSTR lpTempFileNameW;
|
||||
PUNICODE_STRING lpPathNameW;
|
||||
ANSI_STRING TempFileNameStringA;
|
||||
UNICODE_STRING lpPrefixStringW, TempFileNameStringW;
|
||||
|
||||
/* Convert strings */
|
||||
lpPathNameW = Basep8BitStringToStaticUnicodeString(lpPathName);
|
||||
if (!lpPathNameW)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!Basep8BitStringToDynamicUnicodeString(&lpPrefixStringW, lpPrefixString))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
lpTempFileNameW = RtlAllocateHeap(RtlGetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
|
||||
if (!lpTempFileNameW)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
RtlFreeUnicodeString(&lpPrefixStringW);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Call Unicode */
|
||||
ID = GetTempFileNameW(lpPathNameW->Buffer, lpPrefixStringW.Buffer, uUnique, lpTempFileNameW);
|
||||
if (ID)
|
||||
{
|
||||
RtlInitUnicodeString(&TempFileNameStringW, lpTempFileNameW);
|
||||
TempFileNameStringA.Buffer = lpTempFileName;
|
||||
TempFileNameStringA.MaximumLength = MAX_PATH;
|
||||
|
||||
Status = BasepUnicodeStringTo8BitString(&TempFileNameStringA, &TempFileNameStringW, FALSE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
BaseSetLastNTError(Status);
|
||||
ID = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Cleanup */
|
||||
RtlFreeUnicodeString(&lpPrefixStringW);
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, lpTempFileNameW);
|
||||
return ID;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* GetTempFileNameW (KERNEL32.@)
|
||||
*/
|
||||
UINT WINAPI
|
||||
GetTempFileNameW(IN LPCWSTR lpPathName,
|
||||
IN LPCWSTR lpPrefixString,
|
||||
IN UINT uUnique,
|
||||
OUT LPWSTR lpTempFileName)
|
||||
{
|
||||
CHAR * Let;
|
||||
HANDLE TempFile;
|
||||
UINT ID, Num = 0;
|
||||
CHAR IDString[5];
|
||||
WCHAR * TempFileName;
|
||||
CSR_API_MESSAGE ApiMessage;
|
||||
DWORD FileAttributes, LastError;
|
||||
UNICODE_STRING PathNameString, PrefixString;
|
||||
static const WCHAR Ext[] = { L'.', 't', 'm', 'p', UNICODE_NULL };
|
||||
|
||||
RtlInitUnicodeString(&PathNameString, lpPathName);
|
||||
if (PathNameString.Length == 0 || PathNameString.Buffer[(PathNameString.Length / sizeof(WCHAR)) - 1] != L'\\')
|
||||
{
|
||||
PathNameString.Length += sizeof(WCHAR);
|
||||
}
|
||||
|
||||
/* lpTempFileName must be able to contain: PathName, Prefix (3), number(4), .tmp(4) & \0(1)
|
||||
* See: http://msdn.microsoft.com/en-us/library/aa364991%28v=vs.85%29.aspx
|
||||
*/
|
||||
if (PathNameString.Length > (MAX_PATH - 3 - 4 - 4 - 1) * sizeof(WCHAR))
|
||||
{
|
||||
SetLastError(ERROR_BUFFER_OVERFLOW);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If PathName and TempFileName aren't the same buffer, move PathName to TempFileName */
|
||||
if (lpPathName != lpTempFileName)
|
||||
{
|
||||
memmove(lpTempFileName, PathNameString.Buffer, PathNameString.Length);
|
||||
}
|
||||
|
||||
/* PathName MUST BE a path. Check it */
|
||||
lpTempFileName[(PathNameString.Length / sizeof(WCHAR)) - 1] = UNICODE_NULL;
|
||||
FileAttributes = GetFileAttributesW(lpTempFileName);
|
||||
if (FileAttributes == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
/* Append a '\' if necessary */
|
||||
lpTempFileName[(PathNameString.Length / sizeof(WCHAR)) - 1] = L'\\';
|
||||
lpTempFileName[PathNameString.Length / sizeof(WCHAR)] = UNICODE_NULL;
|
||||
FileAttributes = GetFileAttributesW(lpTempFileName);
|
||||
if (FileAttributes == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
SetLastError(ERROR_DIRECTORY);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!(FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||||
{
|
||||
SetLastError(ERROR_DIRECTORY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make sure not to mix path & prefix */
|
||||
lpTempFileName[(PathNameString.Length / sizeof(WCHAR)) - 1] = L'\\';
|
||||
RtlInitUnicodeString(&PrefixString, lpPrefixString);
|
||||
if (PrefixString.Length > 3 * sizeof(WCHAR))
|
||||
{
|
||||
PrefixString.Length = 3 * sizeof(WCHAR);
|
||||
}
|
||||
|
||||
/* Append prefix to path */
|
||||
TempFileName = lpTempFileName + PathNameString.Length / sizeof(WCHAR);
|
||||
memmove(TempFileName, PrefixString.Buffer, PrefixString.Length);
|
||||
TempFileName += PrefixString.Length / sizeof(WCHAR);
|
||||
|
||||
/* Then, generate filename */
|
||||
do
|
||||
{
|
||||
/* If user didn't gave any ID, ask Csrss to give one */
|
||||
if (!uUnique)
|
||||
{
|
||||
CsrClientCallServer(&ApiMessage, NULL, MAKE_CSR_API(GET_TEMP_FILE, CSR_NATIVE), sizeof(CSR_API_MESSAGE));
|
||||
if (ApiMessage.Data.GetTempFile.UniqueID == 0)
|
||||
{
|
||||
Num++;
|
||||
continue;
|
||||
}
|
||||
|
||||
ID = ApiMessage.Data.GetTempFile.UniqueID;
|
||||
}
|
||||
else
|
||||
{
|
||||
ID = uUnique;
|
||||
}
|
||||
|
||||
/* Convert that ID to wchar */
|
||||
RtlIntegerToChar(ID, 0x10, sizeof(IDString), IDString);
|
||||
Let = IDString;
|
||||
do
|
||||
{
|
||||
*(TempFileName++) = RtlAnsiCharToUnicodeChar(&Let);
|
||||
} while (*Let != 0);
|
||||
|
||||
/* Append extension & UNICODE_NULL */
|
||||
memmove(TempFileName, Ext, sizeof(Ext));
|
||||
|
||||
/* If user provided its ID, just return */
|
||||
if (uUnique)
|
||||
{
|
||||
return uUnique;
|
||||
}
|
||||
|
||||
/* Then, try to create file */
|
||||
if (!RtlIsDosDeviceName_U(lpTempFileName))
|
||||
{
|
||||
TempFile = CreateFileW(lpTempFileName,
|
||||
GENERIC_READ,
|
||||
0,
|
||||
NULL,
|
||||
CREATE_NEW,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
0);
|
||||
if (TempFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
NtClose(TempFile);
|
||||
DPRINT("Temp file: %S\n", lpTempFileName);
|
||||
return ID;
|
||||
}
|
||||
|
||||
LastError = GetLastError();
|
||||
/* There is no need to recover from those errors, they would hit next step */
|
||||
if (LastError == ERROR_INVALID_PARAMETER || LastError == ERROR_CANNOT_MAKE ||
|
||||
LastError == ERROR_WRITE_PROTECT || LastError == ERROR_NETWORK_ACCESS_DENIED ||
|
||||
LastError == ERROR_DISK_FULL || LastError == ERROR_INVALID_NAME ||
|
||||
LastError == ERROR_BAD_PATHNAME || LastError == ERROR_NO_INHERITANCE ||
|
||||
LastError == ERROR_DISK_CORRUPT ||
|
||||
(LastError == ERROR_ACCESS_DENIED && NtCurrentTeb()->LastStatusValue != STATUS_FILE_IS_A_DIRECTORY))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
Num++;
|
||||
} while (Num & 0xFFFF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
SetFileShortNameW(
|
||||
HANDLE hFile,
|
||||
LPCWSTR lpShortName)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG NeededSize;
|
||||
UNICODE_STRING ShortName;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
PFILE_NAME_INFORMATION FileNameInfo;
|
||||
|
||||
if(IsConsoleHandle(hFile))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(!lpShortName)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RtlInitUnicodeString(&ShortName, lpShortName);
|
||||
|
||||
NeededSize = sizeof(FILE_NAME_INFORMATION) + ShortName.Length + sizeof(WCHAR);
|
||||
if(!(FileNameInfo = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, NeededSize)))
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FileNameInfo->FileNameLength = ShortName.Length;
|
||||
RtlCopyMemory(FileNameInfo->FileName, ShortName.Buffer, ShortName.Length);
|
||||
|
||||
Status = NtSetInformationFile(hFile,
|
||||
&IoStatusBlock, //out
|
||||
FileNameInfo,
|
||||
NeededSize,
|
||||
FileShortNameInformation);
|
||||
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, FileNameInfo);
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
BaseSetLastNTError(Status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
SetFileShortNameA(
|
||||
HANDLE hFile,
|
||||
LPCSTR lpShortName
|
||||
)
|
||||
{
|
||||
PWCHAR ShortNameW;
|
||||
|
||||
if(IsConsoleHandle(hFile))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(!lpShortName)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!(ShortNameW = FilenameA2W(lpShortName, FALSE)))
|
||||
return FALSE;
|
||||
|
||||
return SetFileShortNameW(hFile, ShortNameW);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
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;
|
||||
AnsiName.MaximumLength = (USHORT)OemNameSize * sizeof(CHAR);
|
||||
AnsiName.Length = 0;
|
||||
}
|
||||
|
||||
RtlInitUnicodeString(&Name, lpName);
|
||||
|
||||
*pbNameLegal = RtlIsNameLegalDOS8Dot3(&Name,
|
||||
(lpOemName ? &AnsiName : NULL),
|
||||
(BOOLEAN*)pbNameContainsSpaces);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
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;
|
||||
AnsiName.MaximumLength = (USHORT)OemNameSize * sizeof(CHAR);
|
||||
AnsiName.Length = 0;
|
||||
}
|
||||
|
||||
RtlInitAnsiString(&AnsiInputName, (LPSTR)lpName);
|
||||
if(bIsFileApiAnsi)
|
||||
Status = RtlAnsiStringToUnicodeString(&Name, &AnsiInputName, TRUE);
|
||||
else
|
||||
Status = RtlOemStringToUnicodeString(&Name, &AnsiInputName, TRUE);
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
BaseSetLastNTError(Status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*pbNameLegal = RtlIsNameLegalDOS8Dot3(&Name,
|
||||
(lpOemName ? &AnsiName : NULL),
|
||||
(BOOLEAN*)pbNameContainsSpaces);
|
||||
|
||||
RtlFreeUnicodeString(&Name);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -168,27 +168,61 @@ PostQueuedCompletionStatus(
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL WINAPI
|
||||
CancelIo(HANDLE hFile)
|
||||
BOOL
|
||||
WINAPI
|
||||
GetOverlappedResult(IN HANDLE hFile,
|
||||
IN LPOVERLAPPED lpOverlapped,
|
||||
OUT LPDWORD lpNumberOfBytesTransferred,
|
||||
IN BOOL bWait)
|
||||
{
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
NTSTATUS Status;
|
||||
DWORD WaitStatus;
|
||||
HANDLE hObject;
|
||||
|
||||
Status = NtCancelIoFile(hFile,
|
||||
&IoStatusBlock);
|
||||
if (!NT_SUCCESS(Status))
|
||||
/* Check for pending operation */
|
||||
if (lpOverlapped->Internal == STATUS_PENDING)
|
||||
{
|
||||
BaseSetLastNTError(Status);
|
||||
return(FALSE);
|
||||
/* Check if the caller is okay with waiting */
|
||||
if (!bWait)
|
||||
{
|
||||
/* Set timeout */
|
||||
WaitStatus = WAIT_TIMEOUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Wait for the result */
|
||||
hObject = lpOverlapped->hEvent ? lpOverlapped->hEvent : hFile;
|
||||
WaitStatus = WaitForSingleObject(hObject, INFINITE);
|
||||
}
|
||||
|
||||
/* Check for timeout */
|
||||
if (WaitStatus == WAIT_TIMEOUT)
|
||||
{
|
||||
/* We have to override the last error with INCOMPLETE instead */
|
||||
SetLastError(ERROR_IO_INCOMPLETE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Fail if we had an error -- the last error is already set */
|
||||
if (WaitStatus != 0) return FALSE;
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
/* Return bytes transferred */
|
||||
*lpNumberOfBytesTransferred = lpOverlapped->InternalHigh;
|
||||
|
||||
/* Check for failure during I/O */
|
||||
if (!NT_SUCCESS(lpOverlapped->Internal))
|
||||
{
|
||||
/* Set the error and fail */
|
||||
BaseSetLastNTError(lpOverlapped->Internal);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* All done */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
|
||||
@@ -793,4 +793,219 @@ MoveFileExA (
|
||||
dwFlags);
|
||||
}
|
||||
|
||||
/*
|
||||
* @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;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
PrivMoveFileIdentityW(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3)
|
||||
{
|
||||
STUB;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Ariadne ( ariadne@xs4all.nl)
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include <k32.h>
|
||||
#define NDEBUG
|
||||
@@ -16,7 +16,114 @@ DEBUG_CHANNEL(kernel32file);
|
||||
|
||||
//#define USING_PROPER_NPFS_WAIT_SEMANTICS
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
LONG ProcessPipeId;
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
CreatePipe(PHANDLE hReadPipe,
|
||||
PHANDLE hWritePipe,
|
||||
LPSECURITY_ATTRIBUTES lpPipeAttributes,
|
||||
DWORD nSize)
|
||||
{
|
||||
WCHAR Buffer[64];
|
||||
UNICODE_STRING PipeName;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
IO_STATUS_BLOCK StatusBlock;
|
||||
LARGE_INTEGER DefaultTimeout;
|
||||
NTSTATUS Status;
|
||||
HANDLE ReadPipeHandle;
|
||||
HANDLE WritePipeHandle;
|
||||
LONG PipeId;
|
||||
ULONG Attributes;
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
|
||||
|
||||
/* Set the timeout to 120 seconds */
|
||||
DefaultTimeout.QuadPart = -1200000000;
|
||||
|
||||
/* Use default buffer size if desired */
|
||||
if (!nSize) nSize = 0x1000;
|
||||
|
||||
/* Increase the Pipe ID */
|
||||
PipeId = InterlockedIncrement(&ProcessPipeId);
|
||||
|
||||
/* Create the pipe name */
|
||||
swprintf(Buffer,
|
||||
L"\\Device\\NamedPipe\\Win32Pipes.%08x.%08x",
|
||||
NtCurrentTeb()->ClientId.UniqueProcess,
|
||||
PipeId);
|
||||
RtlInitUnicodeString(&PipeName, Buffer);
|
||||
|
||||
/* Always use case insensitive */
|
||||
Attributes = OBJ_CASE_INSENSITIVE;
|
||||
|
||||
/* Check if we got attributes */
|
||||
if (lpPipeAttributes)
|
||||
{
|
||||
/* Use the attributes' SD instead */
|
||||
SecurityDescriptor = lpPipeAttributes->lpSecurityDescriptor;
|
||||
|
||||
/* Set OBJ_INHERIT if requested */
|
||||
if (lpPipeAttributes->bInheritHandle) Attributes |= OBJ_INHERIT;
|
||||
}
|
||||
|
||||
/* Initialize the attributes */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&PipeName,
|
||||
Attributes,
|
||||
NULL,
|
||||
SecurityDescriptor);
|
||||
|
||||
/* Create the named pipe */
|
||||
Status = NtCreateNamedPipeFile(&ReadPipeHandle,
|
||||
GENERIC_READ |FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
|
||||
&ObjectAttributes,
|
||||
&StatusBlock,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
FILE_CREATE,
|
||||
FILE_SYNCHRONOUS_IO_NONALERT,
|
||||
FILE_PIPE_BYTE_STREAM_TYPE,
|
||||
FILE_PIPE_BYTE_STREAM_MODE,
|
||||
FILE_PIPE_QUEUE_OPERATION,
|
||||
1,
|
||||
nSize,
|
||||
nSize,
|
||||
&DefaultTimeout);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Convert error and fail */
|
||||
WARN("Status: %lx\n", Status);
|
||||
BaseSetLastNTError(Status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Now try opening it for write access */
|
||||
Status = NtOpenFile(&WritePipeHandle,
|
||||
FILE_GENERIC_WRITE | SYNCHRONIZE,
|
||||
&ObjectAttributes,
|
||||
&StatusBlock,
|
||||
FILE_SHARE_READ,
|
||||
FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Convert error and fail */
|
||||
WARN("Status: %lx\n", Status);
|
||||
NtClose(ReadPipeHandle);
|
||||
BaseSetLastNTError(Status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Return both handles */
|
||||
*hReadPipe = ReadPipeHandle;
|
||||
*hWritePipe = WritePipeHandle;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
/* $Id$
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS system libraries
|
||||
* FILE: lib/kernel32/file/create.c
|
||||
* PURPOSE: Directory functions
|
||||
* PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
|
||||
* UPDATE HISTORY:
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <k32.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
DEBUG_CHANNEL(kernel32file);
|
||||
|
||||
/* GLOBALS ******************************************************************/
|
||||
|
||||
LONG ProcessPipeId = 0;
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
CreatePipe(PHANDLE hReadPipe,
|
||||
PHANDLE hWritePipe,
|
||||
LPSECURITY_ATTRIBUTES lpPipeAttributes,
|
||||
DWORD nSize)
|
||||
{
|
||||
WCHAR Buffer[64];
|
||||
UNICODE_STRING PipeName;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
IO_STATUS_BLOCK StatusBlock;
|
||||
LARGE_INTEGER DefaultTimeout;
|
||||
NTSTATUS Status;
|
||||
HANDLE ReadPipeHandle;
|
||||
HANDLE WritePipeHandle;
|
||||
LONG PipeId;
|
||||
ULONG Attributes;
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
|
||||
|
||||
/* Set the timeout to 120 seconds */
|
||||
DefaultTimeout.QuadPart = -1200000000;
|
||||
|
||||
/* Use default buffer size if desired */
|
||||
if (!nSize) nSize = 0x1000;
|
||||
|
||||
/* Increase the Pipe ID */
|
||||
PipeId = InterlockedIncrement(&ProcessPipeId);
|
||||
|
||||
/* Create the pipe name */
|
||||
swprintf(Buffer,
|
||||
L"\\Device\\NamedPipe\\Win32Pipes.%08x.%08x",
|
||||
NtCurrentTeb()->ClientId.UniqueProcess,
|
||||
PipeId);
|
||||
RtlInitUnicodeString(&PipeName, Buffer);
|
||||
|
||||
/* Always use case insensitive */
|
||||
Attributes = OBJ_CASE_INSENSITIVE;
|
||||
|
||||
/* Check if we got attributes */
|
||||
if (lpPipeAttributes)
|
||||
{
|
||||
/* Use the attributes' SD instead */
|
||||
SecurityDescriptor = lpPipeAttributes->lpSecurityDescriptor;
|
||||
|
||||
/* Set OBJ_INHERIT if requested */
|
||||
if (lpPipeAttributes->bInheritHandle) Attributes |= OBJ_INHERIT;
|
||||
}
|
||||
|
||||
/* Initialize the attributes */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&PipeName,
|
||||
Attributes,
|
||||
NULL,
|
||||
SecurityDescriptor);
|
||||
|
||||
/* Create the named pipe */
|
||||
Status = NtCreateNamedPipeFile(&ReadPipeHandle,
|
||||
GENERIC_READ |FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
|
||||
&ObjectAttributes,
|
||||
&StatusBlock,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
FILE_CREATE,
|
||||
FILE_SYNCHRONOUS_IO_NONALERT,
|
||||
FILE_PIPE_BYTE_STREAM_TYPE,
|
||||
FILE_PIPE_BYTE_STREAM_MODE,
|
||||
FILE_PIPE_QUEUE_OPERATION,
|
||||
1,
|
||||
nSize,
|
||||
nSize,
|
||||
&DefaultTimeout);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Convert error and fail */
|
||||
WARN("Status: %lx\n", Status);
|
||||
BaseSetLastNTError(Status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Now try opening it for write access */
|
||||
Status = NtOpenFile(&WritePipeHandle,
|
||||
FILE_GENERIC_WRITE | SYNCHRONIZE,
|
||||
&ObjectAttributes,
|
||||
&StatusBlock,
|
||||
FILE_SHARE_READ,
|
||||
FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Convert error and fail */
|
||||
WARN("Status: %lx\n", Status);
|
||||
NtClose(ReadPipeHandle);
|
||||
BaseSetLastNTError(Status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Return both handles */
|
||||
*hReadPipe = ReadPipeHandle;
|
||||
*hWritePipe = WritePipeHandle;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -351,4 +351,89 @@ ReadFileEx(IN HANDLE hFile,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
ReadFileScatter(HANDLE hFile,
|
||||
FILE_SEGMENT_ELEMENT aSegmentArray[],
|
||||
DWORD nNumberOfBytesToRead,
|
||||
LPDWORD lpReserved,
|
||||
LPOVERLAPPED lpOverlapped)
|
||||
{
|
||||
PIO_STATUS_BLOCK pIOStatus;
|
||||
LARGE_INTEGER Offset;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("(%p %p %u %p)\n", hFile, aSegmentArray, nNumberOfBytesToRead, lpOverlapped);
|
||||
|
||||
Offset.LowPart = lpOverlapped->Offset;
|
||||
Offset.HighPart = lpOverlapped->OffsetHigh;
|
||||
pIOStatus = (PIO_STATUS_BLOCK) lpOverlapped;
|
||||
pIOStatus->Status = STATUS_PENDING;
|
||||
pIOStatus->Information = 0;
|
||||
|
||||
Status = NtReadFileScatter(hFile,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
pIOStatus,
|
||||
aSegmentArray,
|
||||
nNumberOfBytesToRead,
|
||||
&Offset,
|
||||
NULL);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
SetLastError(RtlNtStatusToDosError(Status));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
WriteFileGather(HANDLE hFile,
|
||||
FILE_SEGMENT_ELEMENT aSegmentArray[],
|
||||
DWORD nNumberOfBytesToWrite,
|
||||
LPDWORD lpReserved,
|
||||
LPOVERLAPPED lpOverlapped)
|
||||
{
|
||||
PIO_STATUS_BLOCK IOStatus;
|
||||
LARGE_INTEGER Offset;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("%p %p %u %p\n", hFile, aSegmentArray, nNumberOfBytesToWrite, lpOverlapped);
|
||||
|
||||
Offset.LowPart = lpOverlapped->Offset;
|
||||
Offset.HighPart = lpOverlapped->OffsetHigh;
|
||||
IOStatus = (PIO_STATUS_BLOCK) lpOverlapped;
|
||||
IOStatus->Status = STATUS_PENDING;
|
||||
IOStatus->Information = 0;
|
||||
|
||||
Status = NtWriteFileGather(hFile,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
IOStatus,
|
||||
aSegmentArray,
|
||||
nNumberOfBytesToWrite,
|
||||
&Offset,
|
||||
NULL);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
SetLastError(RtlNtStatusToDosError(Status));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
||||
@@ -22,9 +22,42 @@
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
UNICODE_STRING Restricted = RTL_CONSTANT_STRING(L"Restricted");
|
||||
BOOL bIsFileApiAnsi = TRUE; // set the file api to ansi or oem
|
||||
PRTL_CONVERT_STRING Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString;
|
||||
PRTL_CONVERT_STRINGA BasepUnicodeStringTo8BitString = RtlUnicodeStringToAnsiString;
|
||||
PRTL_COUNT_STRING BasepUnicodeStringTo8BitSize = BasepUnicodeStringToAnsiSize;
|
||||
PRTL_COUNT_STRINGA Basep8BitStringToUnicodeSize = BasepAnsiStringToUnicodeSize;
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
BasepUnicodeStringToOemSize(IN PUNICODE_STRING String)
|
||||
{
|
||||
return RtlUnicodeStringToOemSize(String);
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
BasepOemStringToUnicodeSize(IN PANSI_STRING String)
|
||||
{
|
||||
return RtlOemStringToUnicodeSize(String);
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
BasepUnicodeStringToAnsiSize(IN PUNICODE_STRING String)
|
||||
{
|
||||
return RtlUnicodeStringToAnsiSize(String);
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
BasepAnsiStringToUnicodeSize(IN PANSI_STRING String)
|
||||
{
|
||||
return RtlAnsiStringToUnicodeSize(String);
|
||||
}
|
||||
|
||||
HANDLE
|
||||
WINAPI
|
||||
BaseGetNamedObjectDirectory(VOID)
|
||||
@@ -680,6 +713,120 @@ BasepMapFile(IN LPCWSTR lpApplicationName,
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN
|
||||
WINAPI
|
||||
Wow64EnableWow64FsRedirection(IN BOOLEAN Wow64EnableWow64FsRedirection)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
BOOL Result;
|
||||
|
||||
Status = RtlWow64EnableFsRedirection(Wow64EnableWow64FsRedirection);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Result = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseSetLastNTError(Status);
|
||||
Result = FALSE;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
Wow64DisableWow64FsRedirection(IN PVOID *OldValue)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
BOOL Result;
|
||||
|
||||
Status = RtlWow64EnableFsRedirectionEx((PVOID)TRUE, OldValue);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Result = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseSetLastNTError(Status);
|
||||
Result = FALSE;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
Wow64RevertWow64FsRedirection(IN PVOID OldValue)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
BOOL Result;
|
||||
|
||||
Status = RtlWow64EnableFsRedirectionEx(OldValue, &OldValue);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Result = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseSetLastNTError(Status);
|
||||
Result = FALSE;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
WINAPI
|
||||
SetFileApisToOEM(VOID)
|
||||
{
|
||||
/* Set the correct Base Api */
|
||||
Basep8BitStringToUnicodeString = (PRTL_CONVERT_STRING)RtlOemStringToUnicodeString;
|
||||
BasepUnicodeStringTo8BitString = RtlUnicodeStringToOemString;
|
||||
BasepUnicodeStringTo8BitSize = BasepUnicodeStringToOemSize;
|
||||
Basep8BitStringToUnicodeSize = BasepOemStringToUnicodeSize;
|
||||
|
||||
/* FIXME: Old, deprecated way */
|
||||
bIsFileApiAnsi = FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
WINAPI
|
||||
SetFileApisToANSI(VOID)
|
||||
{
|
||||
/* Set the correct Base Api */
|
||||
Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString;
|
||||
BasepUnicodeStringTo8BitString = RtlUnicodeStringToAnsiString;
|
||||
BasepUnicodeStringTo8BitSize = BasepUnicodeStringToAnsiSize;
|
||||
Basep8BitStringToUnicodeSize = BasepAnsiStringToUnicodeSize;
|
||||
|
||||
/* FIXME: Old, deprecated way */
|
||||
bIsFileApiAnsi = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
AreFileApisANSI(VOID)
|
||||
{
|
||||
return Basep8BitStringToUnicodeString == RtlAnsiStringToUnicodeString;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
|
||||
@@ -17,6 +17,324 @@
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
|
||||
/* Check whether a file is an OS/2 or a very old Windows executable
|
||||
* by testing on import of KERNEL.
|
||||
*
|
||||
* FIXME: is reading the module imports the only way of discerning
|
||||
* old Windows binaries from OS/2 ones ? At least it seems so...
|
||||
*/
|
||||
static DWORD WINAPI
|
||||
InternalIsOS2OrOldWin(HANDLE hFile, IMAGE_DOS_HEADER *mz, IMAGE_OS2_HEADER *ne)
|
||||
{
|
||||
DWORD CurPos;
|
||||
LPWORD modtab = NULL;
|
||||
LPSTR nametab = NULL;
|
||||
DWORD Read, Ret;
|
||||
int i;
|
||||
|
||||
Ret = BINARY_OS216;
|
||||
CurPos = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
|
||||
|
||||
/* read modref table */
|
||||
if((SetFilePointer(hFile, mz->e_lfanew + ne->ne_modtab, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) ||
|
||||
(!(modtab = HeapAlloc(GetProcessHeap(), 0, ne->ne_cmod * sizeof(WORD)))) ||
|
||||
(!(ReadFile(hFile, modtab, ne->ne_cmod * sizeof(WORD), &Read, NULL))) ||
|
||||
(Read != (DWORD)ne->ne_cmod * sizeof(WORD)))
|
||||
{
|
||||
goto broken;
|
||||
}
|
||||
|
||||
/* read imported names table */
|
||||
if((SetFilePointer(hFile, mz->e_lfanew + ne->ne_imptab, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) ||
|
||||
(!(nametab = HeapAlloc(GetProcessHeap(), 0, ne->ne_enttab - ne->ne_imptab))) ||
|
||||
(!(ReadFile(hFile, nametab, ne->ne_enttab - ne->ne_imptab, &Read, NULL))) ||
|
||||
(Read != (DWORD)ne->ne_enttab - ne->ne_imptab))
|
||||
{
|
||||
goto broken;
|
||||
}
|
||||
|
||||
for(i = 0; i < ne->ne_cmod; i++)
|
||||
{
|
||||
LPSTR module;
|
||||
module = &nametab[modtab[i]];
|
||||
if(!strncmp(&module[1], "KERNEL", module[0]))
|
||||
{
|
||||
/* very old windows file */
|
||||
Ret = BINARY_WIN16;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
broken:
|
||||
DPRINT1("InternalIsOS2OrOldWin(): Binary file seems to be broken\n");
|
||||
|
||||
done:
|
||||
HeapFree(GetProcessHeap(), 0, modtab);
|
||||
HeapFree(GetProcessHeap(), 0, nametab);
|
||||
SetFilePointer(hFile, CurPos, NULL, FILE_BEGIN);
|
||||
return Ret;
|
||||
}
|
||||
|
||||
static DWORD WINAPI
|
||||
InternalGetBinaryType(HANDLE hFile)
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned char magic[4];
|
||||
unsigned char ignored[12];
|
||||
unsigned short type;
|
||||
} elf;
|
||||
struct
|
||||
{
|
||||
unsigned long magic;
|
||||
unsigned long cputype;
|
||||
unsigned long cpusubtype;
|
||||
unsigned long filetype;
|
||||
} macho;
|
||||
IMAGE_DOS_HEADER mz;
|
||||
} Header;
|
||||
char magic[4];
|
||||
DWORD Read;
|
||||
|
||||
if((SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) ||
|
||||
(!ReadFile(hFile, &Header, sizeof(Header), &Read, NULL) ||
|
||||
(Read != sizeof(Header))))
|
||||
{
|
||||
return BINARY_UNKNOWN;
|
||||
}
|
||||
|
||||
if(!memcmp(Header.elf.magic, "\177ELF", sizeof(Header.elf.magic)))
|
||||
{
|
||||
/* FIXME: we don't bother to check byte order, architecture, etc. */
|
||||
switch(Header.elf.type)
|
||||
{
|
||||
case 2:
|
||||
return BINARY_UNIX_EXE;
|
||||
case 3:
|
||||
return BINARY_UNIX_LIB;
|
||||
}
|
||||
return BINARY_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Mach-o File with Endian set to Big Endian or Little Endian*/
|
||||
if(Header.macho.magic == 0xFEEDFACE ||
|
||||
Header.macho.magic == 0xCEFAEDFE)
|
||||
{
|
||||
switch(Header.macho.filetype)
|
||||
{
|
||||
case 0x8:
|
||||
/* MH_BUNDLE */
|
||||
return BINARY_UNIX_LIB;
|
||||
}
|
||||
return BINARY_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Not ELF, try DOS */
|
||||
if(Header.mz.e_magic == IMAGE_DOS_SIGNATURE)
|
||||
{
|
||||
/* We do have a DOS image so we will now try to seek into
|
||||
* the file by the amount indicated by the field
|
||||
* "Offset to extended header" and read in the
|
||||
* "magic" field information at that location.
|
||||
* This will tell us if there is more header information
|
||||
* to read or not.
|
||||
*/
|
||||
if((SetFilePointer(hFile, Header.mz.e_lfanew, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) ||
|
||||
(!ReadFile(hFile, magic, sizeof(magic), &Read, NULL) ||
|
||||
(Read != sizeof(magic))))
|
||||
{
|
||||
return BINARY_DOS;
|
||||
}
|
||||
|
||||
/* Reading the magic field succeeded so
|
||||
* we will try to determine what type it is.
|
||||
*/
|
||||
if(!memcmp(magic, "PE\0\0", sizeof(magic)))
|
||||
{
|
||||
IMAGE_FILE_HEADER FileHeader;
|
||||
if(!ReadFile(hFile, &FileHeader, sizeof(IMAGE_FILE_HEADER), &Read, NULL) ||
|
||||
(Read != sizeof(IMAGE_FILE_HEADER)))
|
||||
{
|
||||
return BINARY_DOS;
|
||||
}
|
||||
|
||||
/* FIXME - detect 32/64 bit */
|
||||
|
||||
if(FileHeader.Characteristics & IMAGE_FILE_DLL)
|
||||
return BINARY_PE_DLL32;
|
||||
return BINARY_PE_EXE32;
|
||||
}
|
||||
|
||||
if(!memcmp(magic, "NE", 1))
|
||||
{
|
||||
/* This is a Windows executable (NE) header. This can
|
||||
* mean either a 16-bit OS/2 or a 16-bit Windows or even a
|
||||
* DOS program (running under a DOS extender). To decide
|
||||
* which, we'll have to read the NE header.
|
||||
*/
|
||||
IMAGE_OS2_HEADER ne;
|
||||
if((SetFilePointer(hFile, Header.mz.e_lfanew, NULL, FILE_BEGIN) == 1) ||
|
||||
!ReadFile(hFile, &ne, sizeof(IMAGE_OS2_HEADER), &Read, NULL) ||
|
||||
(Read != sizeof(IMAGE_OS2_HEADER)))
|
||||
{
|
||||
/* Couldn't read header, so abort. */
|
||||
return BINARY_DOS;
|
||||
}
|
||||
|
||||
switch(ne.ne_exetyp)
|
||||
{
|
||||
case 2:
|
||||
return BINARY_WIN16;
|
||||
case 5:
|
||||
return BINARY_DOS;
|
||||
default:
|
||||
return InternalIsOS2OrOldWin(hFile, &Header.mz, &ne);
|
||||
}
|
||||
}
|
||||
return BINARY_DOS;
|
||||
}
|
||||
return BINARY_UNKNOWN;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
GetBinaryTypeW (
|
||||
LPCWSTR lpApplicationName,
|
||||
LPDWORD lpBinaryType
|
||||
)
|
||||
{
|
||||
HANDLE hFile;
|
||||
DWORD BinType;
|
||||
|
||||
if(!lpApplicationName || !lpBinaryType)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hFile = CreateFileW(lpApplicationName, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||
OPEN_EXISTING, 0, 0);
|
||||
if(hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BinType = InternalGetBinaryType(hFile);
|
||||
CloseHandle(hFile);
|
||||
|
||||
switch(BinType)
|
||||
{
|
||||
case BINARY_UNKNOWN:
|
||||
{
|
||||
WCHAR *dot;
|
||||
|
||||
/*
|
||||
* guess from filename
|
||||
*/
|
||||
if(!(dot = wcsrchr(lpApplicationName, L'.')))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if(!lstrcmpiW(dot, L".COM"))
|
||||
{
|
||||
*lpBinaryType = SCS_DOS_BINARY;
|
||||
return TRUE;
|
||||
}
|
||||
if(!lstrcmpiW(dot, L".PIF"))
|
||||
{
|
||||
*lpBinaryType = SCS_PIF_BINARY;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
case BINARY_PE_EXE32:
|
||||
case BINARY_PE_DLL32:
|
||||
{
|
||||
*lpBinaryType = SCS_32BIT_BINARY;
|
||||
return TRUE;
|
||||
}
|
||||
case BINARY_PE_EXE64:
|
||||
case BINARY_PE_DLL64:
|
||||
{
|
||||
*lpBinaryType = SCS_64BIT_BINARY;
|
||||
return TRUE;
|
||||
}
|
||||
case BINARY_WIN16:
|
||||
{
|
||||
*lpBinaryType = SCS_WOW_BINARY;
|
||||
return TRUE;
|
||||
}
|
||||
case BINARY_OS216:
|
||||
{
|
||||
*lpBinaryType = SCS_OS216_BINARY;
|
||||
return TRUE;
|
||||
}
|
||||
case BINARY_DOS:
|
||||
{
|
||||
*lpBinaryType = SCS_DOS_BINARY;
|
||||
return TRUE;
|
||||
}
|
||||
case BINARY_UNIX_EXE:
|
||||
case BINARY_UNIX_LIB:
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
DPRINT1("Invalid binary type returned!\n", BinType);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
GetBinaryTypeA(IN LPCSTR lpApplicationName,
|
||||
OUT LPDWORD lpBinaryType)
|
||||
{
|
||||
ANSI_STRING ApplicationNameString;
|
||||
UNICODE_STRING ApplicationNameW;
|
||||
BOOL StringAllocated = FALSE, Result;
|
||||
NTSTATUS Status;
|
||||
|
||||
RtlInitAnsiString(&ApplicationNameString, lpApplicationName);
|
||||
|
||||
if (ApplicationNameString.Length * sizeof(WCHAR) >= NtCurrentTeb()->StaticUnicodeString.MaximumLength)
|
||||
{
|
||||
StringAllocated = TRUE;
|
||||
Status = RtlAnsiStringToUnicodeString(&ApplicationNameW, &ApplicationNameString, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = RtlAnsiStringToUnicodeString(&(NtCurrentTeb()->StaticUnicodeString), &ApplicationNameString, FALSE);
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
BaseSetLastNTError(Status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (StringAllocated)
|
||||
{
|
||||
Result = GetBinaryTypeW(ApplicationNameW.Buffer, lpBinaryType);
|
||||
RtlFreeUnicodeString(&ApplicationNameW);
|
||||
}
|
||||
else
|
||||
{
|
||||
Result = GetBinaryTypeW(NtCurrentTeb()->StaticUnicodeString.Buffer, lpBinaryType);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
<file>compname.c</file>
|
||||
<file>debugger.c</file>
|
||||
<file>dllmain.c</file>
|
||||
<file>dosdev.c</file>
|
||||
<file>environ.c</file>
|
||||
<file>except.c</file>
|
||||
<file>fiber.c</file>
|
||||
@@ -56,7 +57,6 @@
|
||||
<file>vista.c</file>
|
||||
<directory name="file">
|
||||
<file>backup.c</file>
|
||||
<file>bintype.c</file>
|
||||
<file>cnotify.c</file>
|
||||
<file>copy.c</file>
|
||||
<file>console.c</file>
|
||||
@@ -64,9 +64,9 @@
|
||||
<file>delete.c</file>
|
||||
<file>deviceio.c</file>
|
||||
<file>dir.c</file>
|
||||
<file>dosdev.c</file>
|
||||
<file>file.c</file>
|
||||
<file>fileinfo.c</file>
|
||||
<file>filemap.c</file>
|
||||
<file>filename.c</file>
|
||||
<file>find.c</file>
|
||||
<file>hardlink.c</file>
|
||||
<file>iocompl.c</file>
|
||||
@@ -75,7 +75,6 @@
|
||||
<file>mailslot.c</file>
|
||||
<file>move.c</file>
|
||||
<file>npipe.c</file>
|
||||
<file>pipe.c</file>
|
||||
<file>rw.c</file>
|
||||
<file>tape.c</file>
|
||||
<file>volume.c</file>
|
||||
|
||||
Reference in New Issue
Block a user