From 784e19a384fe85ddc6dd58b8ccd72fdff88f0e10 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Mon, 7 Nov 2011 00:18:13 +0000 Subject: [PATCH] [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 --- reactos/dll/ntdll/def/ntdll.pspec | 4 +- reactos/dll/ntdll/def/ntdll.spec | 4 +- reactos/dll/ntdll/rtl/libsupp.c | 27 + reactos/dll/win32/kernel32/CMakeLists.txt | 7 +- .../win32/kernel32/client/{file => }/dosdev.c | 0 .../dll/win32/kernel32/client/file/bintype.c | 343 ------ .../dll/win32/kernel32/client/file/create.c | 210 ++++ .../dll/win32/kernel32/client/file/deviceio.c | 56 +- .../client/file/{file.c => fileinfo.c} | 1007 ----------------- .../dll/win32/kernel32/client/file/filename.c | 406 +++++++ .../dll/win32/kernel32/client/file/iocompl.c | 58 +- reactos/dll/win32/kernel32/client/file/move.c | 215 ++++ .../dll/win32/kernel32/client/file/npipe.c | 111 +- reactos/dll/win32/kernel32/client/file/pipe.c | 127 --- reactos/dll/win32/kernel32/client/file/rw.c | 85 ++ reactos/dll/win32/kernel32/client/utils.c | 147 +++ reactos/dll/win32/kernel32/client/vdm.c | 318 ++++++ reactos/dll/win32/kernel32/kernel32.rbuild | 7 +- 18 files changed, 1579 insertions(+), 1553 deletions(-) rename reactos/dll/win32/kernel32/client/{file => }/dosdev.c (100%) delete mode 100644 reactos/dll/win32/kernel32/client/file/bintype.c rename reactos/dll/win32/kernel32/client/file/{file.c => fileinfo.c} (53%) create mode 100644 reactos/dll/win32/kernel32/client/file/filename.c delete mode 100644 reactos/dll/win32/kernel32/client/file/pipe.c diff --git a/reactos/dll/ntdll/def/ntdll.pspec b/reactos/dll/ntdll/def/ntdll.pspec index 35ea604a0fe..ebdd9a6c898 100644 --- a/reactos/dll/ntdll/def/ntdll.pspec +++ b/reactos/dll/ntdll/def/ntdll.pspec @@ -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 diff --git a/reactos/dll/ntdll/def/ntdll.spec b/reactos/dll/ntdll/def/ntdll.spec index f8e11de514c..20234f00cfa 100644 --- a/reactos/dll/ntdll/def/ntdll.spec +++ b/reactos/dll/ntdll/def/ntdll.spec @@ -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 diff --git a/reactos/dll/ntdll/rtl/libsupp.c b/reactos/dll/ntdll/rtl/libsupp.c index 69d42515bf7..6a8ed29f35d 100644 --- a/reactos/dll/ntdll/rtl/libsupp.c +++ b/reactos/dll/ntdll/rtl/libsupp.c @@ -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 */ diff --git a/reactos/dll/win32/kernel32/CMakeLists.txt b/reactos/dll/win32/kernel32/CMakeLists.txt index b7f2ffc03d3..db679ca1e6d 100644 --- a/reactos/dll/win32/kernel32/CMakeLists.txt +++ b/reactos/dll/win32/kernel32/CMakeLists.txt @@ -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 diff --git a/reactos/dll/win32/kernel32/client/file/dosdev.c b/reactos/dll/win32/kernel32/client/dosdev.c similarity index 100% rename from reactos/dll/win32/kernel32/client/file/dosdev.c rename to reactos/dll/win32/kernel32/client/dosdev.c diff --git a/reactos/dll/win32/kernel32/client/file/bintype.c b/reactos/dll/win32/kernel32/client/file/bintype.c deleted file mode 100644 index 824121c395c..00000000000 --- a/reactos/dll/win32/kernel32/client/file/bintype.c +++ /dev/null @@ -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 -#define NDEBUG -#include - -#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 */ diff --git a/reactos/dll/win32/kernel32/client/file/create.c b/reactos/dll/win32/kernel32/client/file/create.c index 282d9918654..1071b42936a 100644 --- a/reactos/dll/win32/kernel32/client/file/create.c +++ b/reactos/dll/win32/kernel32/client/file/create.c @@ -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 */ diff --git a/reactos/dll/win32/kernel32/client/file/deviceio.c b/reactos/dll/win32/kernel32/client/file/deviceio.c index a00ee9b3d64..3f4abbc9392 100644 --- a/reactos/dll/win32/kernel32/client/file/deviceio.c +++ b/reactos/dll/win32/kernel32/client/file/deviceio.c @@ -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 */ - diff --git a/reactos/dll/win32/kernel32/client/file/file.c b/reactos/dll/win32/kernel32/client/file/fileinfo.c similarity index 53% rename from reactos/dll/win32/kernel32/client/file/file.c rename to reactos/dll/win32/kernel32/client/file/fileinfo.c index 066f3570072..81dff79af77 100644 --- a/reactos/dll/win32/kernel32/client/file/file.c +++ b/reactos/dll/win32/kernel32/client/file/fileinfo.c @@ -17,18 +17,8 @@ #include DEBUG_CHANNEL(kernel32file); -/* GLOBALS ******************************************************************/ - -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 ****************************************************************/ - - PWCHAR FilenameA2W(LPCSTR NameA, BOOL alloc) { @@ -179,266 +169,6 @@ FilenameW2A_N( return ret; } -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); -} - -/* - * @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 bIsFileApiAnsi; -} - - -/* - * @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; -} - - /* * @implemented */ @@ -1243,217 +973,6 @@ SetFileAttributesW(LPCWSTR lpFileName, return TRUE; } - - - -/*********************************************************************** - * 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 */ @@ -1670,530 +1189,4 @@ SetFileValidData( return TRUE; } - - -/* - * @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; -} - -/* - * @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; -} - -/* - * @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; -} - -BOOL -WINAPI -OpenDataFile(HANDLE hFile, DWORD dwUnused) -{ - STUB; - return FALSE; -} - -BOOL -WINAPI -PrivMoveFileIdentityW(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) -{ - STUB; - return FALSE; -} - -/* - * @unimplemented - */ -HANDLE -WINAPI -ReOpenFile(IN HANDLE hOriginalFile, - IN DWORD dwDesiredAccess, - IN DWORD dwShareMode, - IN DWORD dwFlags) -{ - STUB; - return INVALID_HANDLE_VALUE; -} - -BOOLEAN -WINAPI -Wow64EnableWow64FsRedirection (BOOLEAN Wow64EnableWow64FsRedirection) -{ - STUB; - return FALSE; -} - -BOOL -WINAPI -Wow64DisableWow64FsRedirection (VOID ** pv) -{ - STUB; - return FALSE; -} - -BOOL -WINAPI -Wow64RevertWow64FsRedirection (VOID * pv) -{ - STUB; - return FALSE; -} - - /* EOF */ diff --git a/reactos/dll/win32/kernel32/client/file/filename.c b/reactos/dll/win32/kernel32/client/file/filename.c new file mode 100644 index 00000000000..a1aa505e97c --- /dev/null +++ b/reactos/dll/win32/kernel32/client/file/filename.c @@ -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 +#define NDEBUG +#include + +/* 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; +} diff --git a/reactos/dll/win32/kernel32/client/file/iocompl.c b/reactos/dll/win32/kernel32/client/file/iocompl.c index 462d2a26cbb..554c9fd1853 100644 --- a/reactos/dll/win32/kernel32/client/file/iocompl.c +++ b/reactos/dll/win32/kernel32/client/file/iocompl.c @@ -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 diff --git a/reactos/dll/win32/kernel32/client/file/move.c b/reactos/dll/win32/kernel32/client/file/move.c index cfbe5f2dfb5..9b23e451678 100644 --- a/reactos/dll/win32/kernel32/client/file/move.c +++ b/reactos/dll/win32/kernel32/client/file/move.c @@ -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 */ diff --git a/reactos/dll/win32/kernel32/client/file/npipe.c b/reactos/dll/win32/kernel32/client/file/npipe.c index 35410a19972..eb54cc6aac2 100644 --- a/reactos/dll/win32/kernel32/client/file/npipe.c +++ b/reactos/dll/win32/kernel32/client/file/npipe.c @@ -7,7 +7,7 @@ * Ariadne ( ariadne@xs4all.nl) */ -/* INCLUDES *****************************************************************/ +/* INCLUDES *******************************************************************/ #include #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 diff --git a/reactos/dll/win32/kernel32/client/file/pipe.c b/reactos/dll/win32/kernel32/client/file/pipe.c deleted file mode 100644 index c4539f70573..00000000000 --- a/reactos/dll/win32/kernel32/client/file/pipe.c +++ /dev/null @@ -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 -#define NDEBUG -#include -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 */ diff --git a/reactos/dll/win32/kernel32/client/file/rw.c b/reactos/dll/win32/kernel32/client/file/rw.c index b5da581edf2..15fbde05972 100644 --- a/reactos/dll/win32/kernel32/client/file/rw.c +++ b/reactos/dll/win32/kernel32/client/file/rw.c @@ -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 */ diff --git a/reactos/dll/win32/kernel32/client/utils.c b/reactos/dll/win32/kernel32/client/utils.c index a4fc1355518..e88a7f5b2f2 100644 --- a/reactos/dll/win32/kernel32/client/utils.c +++ b/reactos/dll/win32/kernel32/client/utils.c @@ -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 */ diff --git a/reactos/dll/win32/kernel32/client/vdm.c b/reactos/dll/win32/kernel32/client/vdm.c index 7ed8780fd09..1f77268d793 100644 --- a/reactos/dll/win32/kernel32/client/vdm.c +++ b/reactos/dll/win32/kernel32/client/vdm.c @@ -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 */ diff --git a/reactos/dll/win32/kernel32/kernel32.rbuild b/reactos/dll/win32/kernel32/kernel32.rbuild index 7094e46a669..1ce9b22d6ce 100644 --- a/reactos/dll/win32/kernel32/kernel32.rbuild +++ b/reactos/dll/win32/kernel32/kernel32.rbuild @@ -30,6 +30,7 @@ compname.c debugger.c dllmain.c + dosdev.c environ.c except.c fiber.c @@ -56,7 +57,6 @@ vista.c backup.c - bintype.c cnotify.c copy.c console.c @@ -64,9 +64,9 @@ delete.c deviceio.c dir.c - dosdev.c - file.c + fileinfo.c filemap.c + filename.c find.c hardlink.c iocompl.c @@ -75,7 +75,6 @@ mailslot.c move.c npipe.c - pipe.c rw.c tape.c volume.c