[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:
Alex Ionescu
2011-11-07 00:18:13 +00:00
parent 35a7096ebc
commit 784e19a384
18 changed files with 1579 additions and 1553 deletions
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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
+27
View File
@@ -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 */
+3 -4
View File
@@ -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 */
@@ -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 */
+109 -2
View File
@@ -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 */
+147
View File
@@ -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
*/
+318
View File
@@ -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
*/
+3 -4
View File
@@ -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>