diff --git a/dlls/kernel/Makefile.in b/dlls/kernel/Makefile.in index 0f88667ee3..50f9ab607c 100644 --- a/dlls/kernel/Makefile.in +++ b/dlls/kernel/Makefile.in @@ -19,7 +19,6 @@ SPEC_SRCS16 = \ C_SRCS = \ $(TOPOBJDIR)/files/directory.c \ - $(TOPOBJDIR)/files/file.c \ $(TOPOBJDIR)/files/smb.c \ $(TOPOBJDIR)/misc/options.c \ $(TOPOBJDIR)/misc/registry.c \ diff --git a/dlls/kernel/file.c b/dlls/kernel/file.c index 5dd744f9c3..1d76e4d638 100644 --- a/dlls/kernel/file.c +++ b/dlls/kernel/file.c @@ -23,6 +23,7 @@ #include "wine/port.h" #include +#include #define NONAMELESSUNION #define NONAMELESSSTRUCT @@ -67,6 +68,103 @@ static WINE_EXCEPTION_FILTER(page_fault) return EXCEPTION_CONTINUE_SEARCH; } + +/*********************************************************************** + * create_file_OF + * + * Wrapper for CreateFile that takes OF_* mode flags. + */ +static HANDLE create_file_OF( LPCSTR path, INT mode, DWORD creation ) +{ + DWORD access, sharing; + + switch(mode & 0x03) + { + case OF_READ: access = GENERIC_READ; break; + case OF_WRITE: access = GENERIC_WRITE; break; + case OF_READWRITE: access = GENERIC_READ | GENERIC_WRITE; break; + default: access = 0; break; + } + switch(mode & 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; break; + } + return CreateFileA( path, access, sharing, NULL, creation, FILE_ATTRIBUTE_NORMAL, 0 ); +} + + +/*********************************************************************** + * FILE_SetDosError + * + * Set the DOS error code from errno. + */ +void FILE_SetDosError(void) +{ + int save_errno = errno; /* errno gets overwritten by printf */ + + TRACE("errno = %d %s\n", errno, strerror(errno)); + switch (save_errno) + { + case EAGAIN: + SetLastError( ERROR_SHARING_VIOLATION ); + break; + case EBADF: + SetLastError( ERROR_INVALID_HANDLE ); + break; + case ENOSPC: + SetLastError( ERROR_HANDLE_DISK_FULL ); + break; + case EACCES: + case EPERM: + case EROFS: + SetLastError( ERROR_ACCESS_DENIED ); + break; + case EBUSY: + SetLastError( ERROR_LOCK_VIOLATION ); + break; + case ENOENT: + SetLastError( ERROR_FILE_NOT_FOUND ); + break; + case EISDIR: + SetLastError( ERROR_CANNOT_MAKE ); + break; + case ENFILE: + case EMFILE: + SetLastError( ERROR_TOO_MANY_OPEN_FILES ); + break; + case EEXIST: + SetLastError( ERROR_FILE_EXISTS ); + break; + case EINVAL: + case ESPIPE: + SetLastError( ERROR_SEEK ); + break; + case ENOTEMPTY: + SetLastError( ERROR_DIR_NOT_EMPTY ); + break; + case ENOEXEC: + SetLastError( ERROR_BAD_FORMAT ); + break; + case ENOTDIR: + SetLastError( ERROR_PATH_NOT_FOUND ); + break; + case EXDEV: + SetLastError( ERROR_NOT_SAME_DEVICE ); + break; + default: + WARN("unknown file error: %s\n", strerror(save_errno) ); + SetLastError( ERROR_GEN_FAILURE ); + break; + } + errno = save_errno; +} + + /************************************************************************** * Operations on file handles * **************************************************************************/ @@ -97,6 +195,183 @@ static void FILE_InitProcessDosHandles( void ) } +/****************************************************************** + * FILE_ReadWriteApc (internal) + */ +static void WINAPI FILE_ReadWriteApc(void* apc_user, PIO_STATUS_BLOCK io_status, ULONG len) +{ + LPOVERLAPPED_COMPLETION_ROUTINE cr = (LPOVERLAPPED_COMPLETION_ROUTINE)apc_user; + + cr(RtlNtStatusToDosError(io_status->u.Status), len, (LPOVERLAPPED)io_status); +} + + +/*********************************************************************** + * ReadFileEx (KERNEL32.@) + */ +BOOL WINAPI ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, + LPOVERLAPPED overlapped, + LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) +{ + LARGE_INTEGER offset; + NTSTATUS status; + PIO_STATUS_BLOCK io_status; + + if (!overlapped) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + offset.u.LowPart = overlapped->Offset; + offset.u.HighPart = overlapped->OffsetHigh; + io_status = (PIO_STATUS_BLOCK)overlapped; + io_status->u.Status = STATUS_PENDING; + + status = NtReadFile(hFile, NULL, FILE_ReadWriteApc, lpCompletionRoutine, + io_status, buffer, bytesToRead, &offset, NULL); + + if (status) + { + SetLastError( RtlNtStatusToDosError(status) ); + return FALSE; + } + return TRUE; +} + + +/*********************************************************************** + * ReadFile (KERNEL32.@) + */ +BOOL WINAPI ReadFile( HANDLE hFile, LPVOID buffer, DWORD bytesToRead, + LPDWORD bytesRead, LPOVERLAPPED overlapped ) +{ + LARGE_INTEGER offset; + PLARGE_INTEGER poffset = NULL; + IO_STATUS_BLOCK iosb; + PIO_STATUS_BLOCK io_status = &iosb; + HANDLE hEvent = 0; + NTSTATUS status; + + TRACE("%p %p %ld %p %p\n", hFile, buffer, bytesToRead, + bytesRead, overlapped ); + + if (bytesRead) *bytesRead = 0; /* Do this before anything else */ + if (!bytesToRead) return TRUE; + + if (IsBadReadPtr(buffer, bytesToRead)) + { + SetLastError(ERROR_WRITE_FAULT); /* FIXME */ + return FALSE; + } + if (is_console_handle(hFile)) + return ReadConsoleA(hFile, buffer, bytesToRead, bytesRead, NULL); + + if (overlapped != NULL) + { + offset.u.LowPart = overlapped->Offset; + offset.u.HighPart = overlapped->OffsetHigh; + poffset = &offset; + hEvent = overlapped->hEvent; + io_status = (PIO_STATUS_BLOCK)overlapped; + } + io_status->u.Status = STATUS_PENDING; + io_status->Information = 0; + + status = NtReadFile(hFile, hEvent, NULL, NULL, io_status, buffer, bytesToRead, poffset, NULL); + + if (status != STATUS_PENDING && bytesRead) + *bytesRead = io_status->Information; + + if (status && status != STATUS_END_OF_FILE) + { + SetLastError( RtlNtStatusToDosError(status) ); + return FALSE; + } + return TRUE; +} + + +/*********************************************************************** + * WriteFileEx (KERNEL32.@) + */ +BOOL WINAPI WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite, + LPOVERLAPPED overlapped, + LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) +{ + LARGE_INTEGER offset; + NTSTATUS status; + PIO_STATUS_BLOCK io_status; + + TRACE("%p %p %ld %p %p\n", hFile, buffer, bytesToWrite, overlapped, lpCompletionRoutine); + + if (overlapped == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + offset.u.LowPart = overlapped->Offset; + offset.u.HighPart = overlapped->OffsetHigh; + + io_status = (PIO_STATUS_BLOCK)overlapped; + io_status->u.Status = STATUS_PENDING; + + status = NtWriteFile(hFile, NULL, FILE_ReadWriteApc, lpCompletionRoutine, + io_status, buffer, bytesToWrite, &offset, NULL); + + if (status) SetLastError( RtlNtStatusToDosError(status) ); + return !status; +} + + +/*********************************************************************** + * WriteFile (KERNEL32.@) + */ +BOOL WINAPI WriteFile( HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite, + LPDWORD bytesWritten, LPOVERLAPPED overlapped ) +{ + HANDLE hEvent = NULL; + LARGE_INTEGER offset; + PLARGE_INTEGER poffset = NULL; + NTSTATUS status; + IO_STATUS_BLOCK iosb; + PIO_STATUS_BLOCK piosb = &iosb; + + TRACE("%p %p %ld %p %p\n", hFile, buffer, bytesToWrite, bytesWritten, overlapped ); + + if (is_console_handle(hFile)) + return WriteConsoleA(hFile, buffer, bytesToWrite, bytesWritten, NULL); + + if (IsBadReadPtr(buffer, bytesToWrite)) + { + SetLastError(ERROR_READ_FAULT); /* FIXME */ + return FALSE; + } + + if (overlapped) + { + offset.u.LowPart = overlapped->Offset; + offset.u.HighPart = overlapped->OffsetHigh; + poffset = &offset; + hEvent = overlapped->hEvent; + piosb = (PIO_STATUS_BLOCK)overlapped; + } + piosb->u.Status = STATUS_PENDING; + piosb->Information = 0; + + status = NtWriteFile(hFile, hEvent, NULL, NULL, piosb, + buffer, bytesToWrite, poffset, NULL); + if (status) + { + SetLastError( RtlNtStatusToDosError(status) ); + return FALSE; + } + if (bytesWritten) *bytesWritten = piosb->Information; + + return TRUE; +} + + /*********************************************************************** * GetOverlappedResult (KERNEL32.@) * @@ -263,11 +538,8 @@ HFILE WINAPI _lcreat( LPCSTR path, INT attr ) */ HFILE WINAPI _lopen( LPCSTR path, INT mode ) { - DWORD access, sharing; - - TRACE("('%s',%04x)\n", path, mode ); - FILE_ConvertOFMode( mode, &access, &sharing ); - return (HFILE)CreateFileA( path, access, sharing, NULL, OPEN_EXISTING, 0, 0 ); + TRACE("(%s,%04x)\n", debugstr_a(path), mode ); + return (HFILE)create_file_OF( path, mode, OPEN_EXISTING ); } @@ -447,6 +719,54 @@ BOOL WINAPI SetEndOfFile( HANDLE hFile ) } +/*********************************************************************** + * SetFilePointer (KERNEL32.@) + */ +DWORD WINAPI SetFilePointer( HANDLE hFile, LONG distance, LONG *highword, + DWORD method ) +{ + static const int whence[3] = { SEEK_SET, SEEK_CUR, SEEK_END }; + DWORD ret = INVALID_SET_FILE_POINTER; + NTSTATUS status; + int fd; + + TRACE("handle %p offset %ld high %ld origin %ld\n", + hFile, distance, highword?*highword:0, method ); + + if (method > FILE_END) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return ret; + } + + if (!(status = wine_server_handle_to_fd( hFile, 0, &fd, NULL, NULL ))) + { + off_t pos, res; + + if (highword) pos = ((off_t)*highword << 32) | (ULONG)distance; + else pos = (off_t)distance; + if ((res = lseek( fd, pos, whence[method] )) == (off_t)-1) + { + /* also check EPERM due to SuSE7 2.2.16 lseek() EPERM kernel bug */ + if (((errno == EINVAL) || (errno == EPERM)) && (method != FILE_BEGIN) && (pos < 0)) + SetLastError( ERROR_NEGATIVE_SEEK ); + else + FILE_SetDosError(); + } + else + { + ret = (DWORD)res; + if (highword) *highword = (res >> 32); + if (ret == INVALID_SET_FILE_POINTER) SetLastError( 0 ); + } + wine_server_release_fd( hFile, fd ); + } + else SetLastError( RtlNtStatusToDosError(status) ); + + return ret; +} + + /*********************************************************************** * GetFileTime (KERNEL32.@) */ @@ -674,6 +994,15 @@ HANDLE WINAPI DosFileHandleToWin32Handle( HFILE handle ) } +/************************************************************************* + * SetHandleCount (KERNEL32.@) + */ +UINT WINAPI SetHandleCount( UINT count ) +{ + return min( 256, count ); +} + + /*********************************************************************** * DisposeLZ32Handle (KERNEL32.22) * @@ -701,6 +1030,221 @@ void WINAPI DisposeLZ32Handle( HANDLE handle ) * Operations on file names * **************************************************************************/ + +/************************************************************************* + * CreateFileW [KERNEL32.@] Creates or opens a file or other object + * + * Creates or opens an object, and returns a handle that can be used to + * access that object. + * + * PARAMS + * + * filename [in] pointer to filename to be accessed + * access [in] access mode requested + * sharing [in] share mode + * sa [in] pointer to security attributes + * creation [in] how to create the file + * attributes [in] attributes for newly created file + * template [in] handle to file with extended attributes to copy + * + * RETURNS + * Success: Open handle to specified file + * Failure: INVALID_HANDLE_VALUE + */ +HANDLE WINAPI CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing, + LPSECURITY_ATTRIBUTES sa, DWORD creation, + DWORD attributes, HANDLE template ) +{ + NTSTATUS status; + UINT options; + OBJECT_ATTRIBUTES attr; + UNICODE_STRING nameW; + IO_STATUS_BLOCK io; + HANDLE ret; + DWORD dosdev; + static const WCHAR bkslashes_with_dotW[] = {'\\','\\','.','\\',0}; + static const WCHAR coninW[] = {'C','O','N','I','N','$',0}; + static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0}; + + static const char * const creation_name[5] = + { "CREATE_NEW", "CREATE_ALWAYS", "OPEN_EXISTING", "OPEN_ALWAYS", "TRUNCATE_EXISTING" }; + + static const UINT nt_disposition[5] = + { + FILE_CREATE, /* CREATE_NEW */ + FILE_OVERWRITE_IF, /* CREATE_ALWAYS */ + FILE_OPEN, /* OPEN_EXISTING */ + FILE_OPEN_IF, /* OPEN_ALWAYS */ + FILE_OVERWRITE /* TRUNCATE_EXISTING */ + }; + + + /* sanity checks */ + + if (!filename || !filename[0]) + { + SetLastError( ERROR_PATH_NOT_FOUND ); + return INVALID_HANDLE_VALUE; + } + + if (creation < CREATE_NEW || creation > TRUNCATE_EXISTING) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return INVALID_HANDLE_VALUE; + } + + TRACE("%s %s%s%s%s%s%s%s attributes 0x%lx\n", debugstr_w(filename), + (access & GENERIC_READ)?"GENERIC_READ ":"", + (access & GENERIC_WRITE)?"GENERIC_WRITE ":"", + (!access)?"QUERY_ACCESS ":"", + (sharing & FILE_SHARE_READ)?"FILE_SHARE_READ ":"", + (sharing & FILE_SHARE_WRITE)?"FILE_SHARE_WRITE ":"", + (sharing & FILE_SHARE_DELETE)?"FILE_SHARE_DELETE ":"", + creation_name[creation - CREATE_NEW], attributes); + + /* Open a console for CONIN$ or CONOUT$ */ + + if (!strcmpiW(filename, coninW) || !strcmpiW(filename, conoutW)) + { + ret = OpenConsoleW(filename, access, (sa && sa->bInheritHandle), creation); + goto done; + } + + if (!strncmpW(filename, bkslashes_with_dotW, 4)) + { + static const WCHAR pipeW[] = {'P','I','P','E','\\',0}; + + if ((isalphaW(filename[4]) && filename[5] == ':' && filename[6] == '\0') || + !strncmpiW( filename + 4, pipeW, 5 )) + { + dosdev = 0; + } + else if ((dosdev = RtlIsDosDeviceName_U( filename + 4 ))) + { + dosdev += MAKELONG( 0, 4*sizeof(WCHAR) ); /* adjust position to start of filename */ + } + else if (filename[4]) + { + ret = VXD_Open( filename+4, access, sa ); + goto done; + } + else + { + SetLastError( ERROR_INVALID_NAME ); + return INVALID_HANDLE_VALUE; + } + } + else dosdev = RtlIsDosDeviceName_U( filename ); + + if (dosdev) + { + static const WCHAR conW[] = {'C','O','N'}; + + if (LOWORD(dosdev) == sizeof(conW) && + !memicmpW( filename + HIWORD(dosdev)/sizeof(WCHAR), conW, sizeof(conW))) + { + switch (access & (GENERIC_READ|GENERIC_WRITE)) + { + case GENERIC_READ: + ret = OpenConsoleW(coninW, access, (sa && sa->bInheritHandle), creation); + goto done; + case GENERIC_WRITE: + ret = OpenConsoleW(conoutW, access, (sa && sa->bInheritHandle), creation); + goto done; + default: + SetLastError( ERROR_FILE_NOT_FOUND ); + return INVALID_HANDLE_VALUE; + } + } + } + + if (!RtlDosPathNameToNtPathName_U( filename, &nameW, NULL, NULL )) + { + SetLastError( ERROR_PATH_NOT_FOUND ); + return INVALID_HANDLE_VALUE; + } + + /* now call NtCreateFile */ + + options = 0; + if (attributes & FILE_FLAG_BACKUP_SEMANTICS) + options |= FILE_OPEN_FOR_BACKUP_INTENT; + else + options |= FILE_NON_DIRECTORY_FILE; + if (attributes & FILE_FLAG_DELETE_ON_CLOSE) + options |= FILE_DELETE_ON_CLOSE; + if (!(attributes & FILE_FLAG_OVERLAPPED)) + options |= FILE_SYNCHRONOUS_IO_ALERT; + if (attributes & FILE_FLAG_RANDOM_ACCESS) + options |= FILE_RANDOM_ACCESS; + attributes &= FILE_ATTRIBUTE_VALID_FLAGS; + + attr.Length = sizeof(attr); + attr.RootDirectory = 0; + attr.Attributes = OBJ_CASE_INSENSITIVE; + attr.ObjectName = &nameW; + attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL; + attr.SecurityQualityOfService = NULL; + + if (sa && sa->bInheritHandle) attr.Attributes |= OBJ_INHERIT; + + status = NtCreateFile( &ret, access, &attr, &io, NULL, attributes, + sharing, nt_disposition[creation - CREATE_NEW], + options, NULL, 0 ); + if (status) + { + WARN("Unable to create file %s (status %lx)\n", debugstr_w(filename), status); + ret = INVALID_HANDLE_VALUE; + + /* In the case file creation was rejected due to CREATE_NEW flag + * was specified and file with that name already exists, correct + * last error is ERROR_FILE_EXISTS and not ERROR_ALREADY_EXISTS. + * Note: RtlNtStatusToDosError is not the subject to blame here. + */ + if (status == STATUS_OBJECT_NAME_COLLISION) + SetLastError( ERROR_FILE_EXISTS ); + else + SetLastError( RtlNtStatusToDosError(status) ); + } + else SetLastError(0); + RtlFreeUnicodeString( &nameW ); + + done: + if (!ret) ret = INVALID_HANDLE_VALUE; + TRACE("returning %p\n", ret); + return ret; +} + + + +/************************************************************************* + * CreateFileA (KERNEL32.@) + */ +HANDLE WINAPI CreateFileA( LPCSTR filename, DWORD access, DWORD sharing, + LPSECURITY_ATTRIBUTES sa, DWORD creation, + DWORD attributes, HANDLE template) +{ + UNICODE_STRING filenameW; + HANDLE ret = INVALID_HANDLE_VALUE; + + if (!filename) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return INVALID_HANDLE_VALUE; + } + + if (RtlCreateUnicodeStringFromAsciiz(&filenameW, filename)) + { + ret = CreateFileW(filenameW.Buffer, access, sharing, sa, creation, + attributes, template); + RtlFreeUnicodeString(&filenameW); + } + else + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return ret; +} + + /*********************************************************************** * DeleteFileW (KERNEL32.@) */ @@ -1400,11 +1944,7 @@ HFILE WINAPI OpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode ) if (mode & OF_CREATE) { - DWORD access, sharing; - FILE_ConvertOFMode( mode, &access, &sharing ); - if ((handle = CreateFileA( name, GENERIC_READ | GENERIC_WRITE, - sharing, NULL, CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, 0 )) == INVALID_HANDLE_VALUE) + if ((handle = create_file_OF( name, mode, CREATE_ALWAYS )) == INVALID_HANDLE_VALUE) goto error; } else diff --git a/dlls/kernel/file16.c b/dlls/kernel/file16.c index 9da451722e..bcd1685c47 100644 --- a/dlls/kernel/file16.c +++ b/dlls/kernel/file16.c @@ -147,40 +147,30 @@ HFILE16 WINAPI OpenFile16( LPCSTR name, OFSTRUCT *ofs, UINT16 mode ) ((mode & OF_REOPEN )==OF_REOPEN)?"OF_REOPEN ":"" ); - ofs->cBytes = sizeof(OFSTRUCT); - ofs->nErrCode = 0; - if (mode & OF_REOPEN) name = ofs->szPathName; - - if (!name) return HFILE_ERROR; - - /* the watcom 10.6 IDE relies on a valid path returned in ofs->szPathName - Are there any cases where getting the path here is wrong? - Uwe Bonnes 1997 Apr 2 */ - if (!GetFullPathNameA( name, sizeof(ofs->szPathName), ofs->szPathName, NULL )) goto error; - - /* OF_PARSE simply fills the structure */ - if (mode & OF_PARSE) { - ofs->fFixedDisk = (GetDriveType16( ofs->szPathName[0]-'A' ) != DRIVE_REMOVABLE); - TRACE("(%s): OF_PARSE, res = '%s'\n", name, ofs->szPathName ); + OpenFile( name, ofs, mode ); return 0; } - /* OF_CREATE is completely different from all other options, so - handle it first */ - if (mode & OF_CREATE) { - DWORD access, sharing; - FILE_ConvertOFMode( mode, &access, &sharing ); - if ((handle = CreateFileA( ofs->szPathName, GENERIC_READ | GENERIC_WRITE, - sharing, NULL, CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, 0 ))== INVALID_HANDLE_VALUE) - goto error; + handle = (HANDLE)OpenFile( name, ofs, mode ); + if (handle == (HANDLE)HFILE_ERROR) goto error; } else { + ofs->cBytes = sizeof(OFSTRUCT); + ofs->nErrCode = 0; + if (mode & OF_REOPEN) name = ofs->szPathName; + + if (!name) return HFILE_ERROR; + + /* the watcom 10.6 IDE relies on a valid path returned in ofs->szPathName + Are there any cases where getting the path here is wrong? + Uwe Bonnes 1997 Apr 2 */ + if (!GetFullPathNameA( name, sizeof(ofs->szPathName), ofs->szPathName, NULL )) goto error; + /* If OF_SEARCH is set, ignore the given path */ filename = name; diff --git a/dlls/kernel/kernel_main.c b/dlls/kernel/kernel_main.c index 16588807cf..43119c1447 100644 --- a/dlls/kernel/kernel_main.c +++ b/dlls/kernel/kernel_main.c @@ -36,7 +36,6 @@ #include "wine/winbase16.h" #include "wine/library.h" -#include "file.h" #include "miscemu.h" #include "module.h" #include "thread.h" diff --git a/dlls/kernel/kernel_private.h b/dlls/kernel/kernel_private.h index dddc742174..2c43196897 100644 --- a/dlls/kernel/kernel_private.h +++ b/dlls/kernel/kernel_private.h @@ -49,13 +49,14 @@ extern HMODULE kernel32_handle; /* Size of per-process table of DOS handles */ #define DOS_TABLE_SIZE 256 extern HANDLE dos_handles[DOS_TABLE_SIZE]; -void FILE_ConvertOFMode( INT mode, DWORD *access, DWORD *sharing ); extern void PTHREAD_Init(void); extern BOOL WOWTHUNK_Init(void); extern VOID SYSLEVEL_CheckNotLevel( INT level ); +extern void FILE_SetDosError(void); + extern DWORD INSTR_EmulateInstruction( EXCEPTION_RECORD *rec, CONTEXT86 *context ); extern void INSTR_CallBuiltinHandler( CONTEXT86 *context, BYTE intnum ); @@ -69,6 +70,8 @@ extern void SELECTOR_FreeBlock( WORD sel ); #define IS_SELECTOR_32BIT(sel) \ (wine_ldt_is_system(sel) || (wine_ldt_copy.flags[LOWORD(sel) >> 3] & WINE_LDT_FLAGS_32BIT)) +extern HANDLE VXD_Open( LPCWSTR filename, DWORD access, LPSECURITY_ATTRIBUTES sa ); + /* this structure is always located at offset 0 of the DGROUP segment */ #include "pshpack1.h" typedef struct diff --git a/dlls/kernel/path.c b/dlls/kernel/path.c index 9de9fde4ed..919f216569 100644 --- a/dlls/kernel/path.c +++ b/dlls/kernel/path.c @@ -2,7 +2,7 @@ * File handling functions * * Copyright 1993 Erik Bos - * Copyright 1996 Alexandre Julliard + * Copyright 1996, 2004 Alexandre Julliard * Copyright 2003 Eric Pouech * * This library is free software; you can redistribute it and/or @@ -38,7 +38,6 @@ #include "winternl.h" #include "kernel_private.h" -#include "file.h" #include "wine/unicode.h" #include "wine/debug.h" @@ -669,6 +668,91 @@ UINT WINAPI GetTempPathW( UINT count, LPWSTR path ) } +/*********************************************************************** + * GetTempFileNameA (KERNEL32.@) + */ +UINT WINAPI GetTempFileNameA( LPCSTR path, LPCSTR prefix, UINT unique, LPSTR buffer) +{ + UNICODE_STRING pathW, prefixW; + WCHAR bufferW[MAX_PATH]; + UINT ret; + + if ( !path || !prefix || !buffer ) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + + RtlCreateUnicodeStringFromAsciiz(&pathW, path); + RtlCreateUnicodeStringFromAsciiz(&prefixW, prefix); + + ret = GetTempFileNameW(pathW.Buffer, prefixW.Buffer, unique, bufferW); + if (ret) + WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buffer, MAX_PATH, NULL, NULL); + + RtlFreeUnicodeString(&pathW); + RtlFreeUnicodeString(&prefixW); + return ret; +} + +/*********************************************************************** + * GetTempFileNameW (KERNEL32.@) + */ +UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique, LPWSTR buffer ) +{ + static const WCHAR formatW[] = {'%','x','.','t','m','p',0}; + + int i; + LPWSTR p; + + if ( !path || !prefix || !buffer ) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + + strcpyW( buffer, path ); + p = buffer + strlenW(buffer); + + /* add a \, if there isn't one */ + if ((p == buffer) || (p[-1] != '\\')) *p++ = '\\'; + + for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++; + + unique &= 0xffff; + + if (unique) sprintfW( p, formatW, unique ); + else + { + /* get a "random" unique number and try to create the file */ + HANDLE handle; + UINT num = GetTickCount() & 0xffff; + + if (!num) num = 1; + unique = num; + do + { + sprintfW( p, formatW, unique ); + handle = CreateFileW( buffer, GENERIC_WRITE, 0, NULL, + CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 ); + if (handle != INVALID_HANDLE_VALUE) + { /* We created it */ + TRACE("created %s\n", debugstr_w(buffer) ); + CloseHandle( handle ); + break; + } + if (GetLastError() != ERROR_FILE_EXISTS && + GetLastError() != ERROR_SHARING_VIOLATION) + break; /* No need to go on */ + if (!(++unique & 0xffff)) unique = 1; + } while (unique != num); + } + + TRACE("returning %s\n", debugstr_w(buffer) ); + return unique; +} + + /*********************************************************************** * contains_pathW * @@ -822,6 +906,138 @@ DWORD WINAPI SearchPathA( LPCSTR path, LPCSTR name, LPCSTR ext, } +/************************************************************************** + * CopyFileW (KERNEL32.@) + */ +BOOL WINAPI CopyFileW( LPCWSTR source, LPCWSTR dest, BOOL fail_if_exists ) +{ + HANDLE h1, h2; + BY_HANDLE_FILE_INFORMATION info; + DWORD count; + BOOL ret = FALSE; + char buffer[2048]; + + if (!source || !dest) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + TRACE("%s -> %s\n", debugstr_w(source), debugstr_w(dest)); + + if ((h1 = CreateFileW(source, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) + { + WARN("Unable to open source %s\n", debugstr_w(source)); + return FALSE; + } + + if (!GetFileInformationByHandle( h1, &info )) + { + WARN("GetFileInformationByHandle returned error for %s\n", debugstr_w(source)); + CloseHandle( h1 ); + return FALSE; + } + + if ((h2 = CreateFileW( dest, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + fail_if_exists ? CREATE_NEW : CREATE_ALWAYS, + info.dwFileAttributes, h1 )) == INVALID_HANDLE_VALUE) + { + WARN("Unable to open dest %s\n", debugstr_w(dest)); + CloseHandle( h1 ); + return FALSE; + } + + while (ReadFile( h1, buffer, sizeof(buffer), &count, NULL ) && count) + { + char *p = buffer; + while (count != 0) + { + DWORD res; + if (!WriteFile( h2, p, count, &res, NULL ) || !res) goto done; + p += res; + count -= res; + } + } + ret = TRUE; +done: + CloseHandle( h1 ); + CloseHandle( h2 ); + return ret; +} + + +/************************************************************************** + * CopyFileA (KERNEL32.@) + */ +BOOL WINAPI CopyFileA( LPCSTR source, LPCSTR dest, BOOL fail_if_exists) +{ + UNICODE_STRING sourceW, destW; + BOOL ret; + + if (!source || !dest) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + RtlCreateUnicodeStringFromAsciiz(&sourceW, source); + RtlCreateUnicodeStringFromAsciiz(&destW, dest); + + ret = CopyFileW(sourceW.Buffer, destW.Buffer, fail_if_exists); + + RtlFreeUnicodeString(&sourceW); + RtlFreeUnicodeString(&destW); + return ret; +} + + +/************************************************************************** + * CopyFileExW (KERNEL32.@) + * + * This implementation ignores most of the extra parameters passed-in into + * the "ex" version of the method and calls the CopyFile method. + * It will have to be fixed eventually. + */ +BOOL WINAPI CopyFileExW(LPCWSTR sourceFilename, LPCWSTR destFilename, + LPPROGRESS_ROUTINE progressRoutine, LPVOID appData, + LPBOOL cancelFlagPointer, DWORD copyFlags) +{ + /* + * Interpret the only flag that CopyFile can interpret. + */ + return CopyFileW(sourceFilename, destFilename, (copyFlags & COPY_FILE_FAIL_IF_EXISTS) != 0); +} + + +/************************************************************************** + * CopyFileExA (KERNEL32.@) + */ +BOOL WINAPI CopyFileExA(LPCSTR sourceFilename, LPCSTR destFilename, + LPPROGRESS_ROUTINE progressRoutine, LPVOID appData, + LPBOOL cancelFlagPointer, DWORD copyFlags) +{ + UNICODE_STRING sourceW, destW; + BOOL ret; + + if (!sourceFilename || !destFilename) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + RtlCreateUnicodeStringFromAsciiz(&sourceW, sourceFilename); + RtlCreateUnicodeStringFromAsciiz(&destW, destFilename); + + ret = CopyFileExW(sourceW.Buffer, destW.Buffer, progressRoutine, appData, + cancelFlagPointer, copyFlags); + + RtlFreeUnicodeString(&sourceW); + RtlFreeUnicodeString(&destW); + return ret; +} + + /************************************************************************** * MoveFileExW (KERNEL32.@) */ diff --git a/dlls/kernel/process.c b/dlls/kernel/process.c index e5e3bd22aa..ffca8f4caf 100644 --- a/dlls/kernel/process.c +++ b/dlls/kernel/process.c @@ -37,7 +37,6 @@ #include "wine/winuser16.h" #include "ntstatus.h" #include "thread.h" -#include "file.h" #include "module.h" #include "options.h" #include "kernel_private.h" @@ -82,6 +81,7 @@ static const WCHAR comW[] = {'.','c','o','m',0}; static const WCHAR batW[] = {'.','b','a','t',0}; static const WCHAR winevdmW[] = {'w','i','n','e','v','d','m','.','e','x','e',0}; +extern int DIR_Init(void); extern void SHELL_LoadRegistry(void); extern void VOLUME_CreateDevices(void); extern void VERSION_Init( const WCHAR *appname ); diff --git a/dlls/kernel/profile.c b/dlls/kernel/profile.c index 4a78080a0e..92dd1bf044 100644 --- a/dlls/kernel/profile.c +++ b/dlls/kernel/profile.c @@ -32,7 +32,6 @@ #include "winreg.h" #include "winternl.h" #include "wine/winbase16.h" -#include "file.h" #include "wine/unicode.h" #include "wine/server.h" #include "wine/library.h" diff --git a/dlls/kernel/task.c b/dlls/kernel/task.c index b477e9595a..394c652934 100644 --- a/dlls/kernel/task.c +++ b/dlls/kernel/task.c @@ -37,7 +37,6 @@ #include "winuser.h" #include "wine/winbase16.h" -#include "file.h" #include "module.h" #include "winternl.h" #include "wine/server.h" diff --git a/dlls/kernel/volume.c b/dlls/kernel/volume.c index b32ad474f4..560e9497fe 100644 --- a/dlls/kernel/volume.c +++ b/dlls/kernel/volume.c @@ -39,7 +39,6 @@ #include "ntddstor.h" #include "ntddcdrm.h" #include "kernel_private.h" -#include "file.h" #include "wine/library.h" #include "wine/unicode.h" #include "wine/debug.h" diff --git a/dlls/kernel/vxd.c b/dlls/kernel/vxd.c index b34bec37ee..cf7eab3af6 100644 --- a/dlls/kernel/vxd.c +++ b/dlls/kernel/vxd.c @@ -36,7 +36,6 @@ #include "winbase.h" #include "winreg.h" #include "winerror.h" -#include "file.h" #include "kernel_private.h" #include "wine/library.h" #include "wine/unicode.h" diff --git a/files/directory.c b/files/directory.c index 26b8776447..b139cc4fda 100644 --- a/files/directory.c +++ b/files/directory.c @@ -46,12 +46,13 @@ #include "winternl.h" #include "thread.h" #include "wine/unicode.h" -#include "file.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(dosfs); WINE_DECLARE_DEBUG_CHANNEL(file); +#define MAX_PATHNAME_LEN 1024 + static WCHAR *DIR_Windows; static WCHAR *DIR_System; diff --git a/files/file.c b/files/file.c deleted file mode 100644 index ae5859da2b..0000000000 --- a/files/file.c +++ /dev/null @@ -1,850 +0,0 @@ -/* - * File handling functions - * - * Copyright 1993 John Burton - * Copyright 1996 Alexandre Julliard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * TODO: - * Fix the CopyFileEx methods to implement the "extended" functionality. - * Right now, they simply call the CopyFile method. - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_SYS_ERRNO_H -#include -#endif -#include -#include -#ifdef HAVE_SYS_MMAN_H -#include -#endif -#ifdef HAVE_SYS_TIME_H -# include -#endif -#ifdef HAVE_SYS_POLL_H -# include -#endif -#include -#ifdef HAVE_UNISTD_H -# include -#endif -#ifdef HAVE_UTIME_H -# include -#endif -#ifdef HAVE_IO_H -# include -#endif - -#define NONAMELESSUNION -#define NONAMELESSSTRUCT -#include "winerror.h" -#include "ntstatus.h" -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "winternl.h" -#include "wine/winbase16.h" -#include "wine/server.h" - -#include "file.h" -#include "wincon.h" -#include "kernel_private.h" - -#include "smb.h" -#include "wine/unicode.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(file); - - -/*********************************************************************** - * FILE_ConvertOFMode - * - * Convert OF_* mode into flags for CreateFile. - */ -void FILE_ConvertOFMode( INT mode, DWORD *access, DWORD *sharing ) -{ - switch(mode & 0x03) - { - case OF_READ: *access = GENERIC_READ; break; - case OF_WRITE: *access = GENERIC_WRITE; break; - case OF_READWRITE: *access = GENERIC_READ | GENERIC_WRITE; break; - default: *access = 0; break; - } - switch(mode & 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; break; - } -} - - -/*********************************************************************** - * FILE_SetDosError - * - * Set the DOS error code from errno. - */ -void FILE_SetDosError(void) -{ - int save_errno = errno; /* errno gets overwritten by printf */ - - TRACE("errno = %d %s\n", errno, strerror(errno)); - switch (save_errno) - { - case EAGAIN: - SetLastError( ERROR_SHARING_VIOLATION ); - break; - case EBADF: - SetLastError( ERROR_INVALID_HANDLE ); - break; - case ENOSPC: - SetLastError( ERROR_HANDLE_DISK_FULL ); - break; - case EACCES: - case EPERM: - case EROFS: - SetLastError( ERROR_ACCESS_DENIED ); - break; - case EBUSY: - SetLastError( ERROR_LOCK_VIOLATION ); - break; - case ENOENT: - SetLastError( ERROR_FILE_NOT_FOUND ); - break; - case EISDIR: - SetLastError( ERROR_CANNOT_MAKE ); - break; - case ENFILE: - case EMFILE: - SetLastError( ERROR_TOO_MANY_OPEN_FILES ); - break; - case EEXIST: - SetLastError( ERROR_FILE_EXISTS ); - break; - case EINVAL: - case ESPIPE: - SetLastError( ERROR_SEEK ); - break; - case ENOTEMPTY: - SetLastError( ERROR_DIR_NOT_EMPTY ); - break; - case ENOEXEC: - SetLastError( ERROR_BAD_FORMAT ); - break; - case ENOTDIR: - SetLastError( ERROR_PATH_NOT_FOUND ); - break; - case EXDEV: - SetLastError( ERROR_NOT_SAME_DEVICE ); - break; - default: - WARN("unknown file error: %s\n", strerror(save_errno) ); - SetLastError( ERROR_GEN_FAILURE ); - break; - } - errno = save_errno; -} - - -/************************************************************************* - * CreateFileW [KERNEL32.@] Creates or opens a file or other object - * - * Creates or opens an object, and returns a handle that can be used to - * access that object. - * - * PARAMS - * - * filename [in] pointer to filename to be accessed - * access [in] access mode requested - * sharing [in] share mode - * sa [in] pointer to security attributes - * creation [in] how to create the file - * attributes [in] attributes for newly created file - * template [in] handle to file with extended attributes to copy - * - * RETURNS - * Success: Open handle to specified file - * Failure: INVALID_HANDLE_VALUE - * - * NOTES - * Should call SetLastError() on failure. - * - * BUGS - * - * Doesn't support character devices, template files, or a - * lot of the 'attributes' flags yet. - */ -HANDLE WINAPI CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing, - LPSECURITY_ATTRIBUTES sa, DWORD creation, - DWORD attributes, HANDLE template ) -{ - NTSTATUS status; - UINT options; - OBJECT_ATTRIBUTES attr; - UNICODE_STRING nameW; - IO_STATUS_BLOCK io; - HANDLE ret; - DWORD dosdev; - static const WCHAR bkslashes_with_dotW[] = {'\\','\\','.','\\',0}; - static const WCHAR coninW[] = {'C','O','N','I','N','$',0}; - static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0}; - - static const char * const creation_name[5] = - { "CREATE_NEW", "CREATE_ALWAYS", "OPEN_EXISTING", "OPEN_ALWAYS", "TRUNCATE_EXISTING" }; - - static const UINT nt_disposition[5] = - { - FILE_CREATE, /* CREATE_NEW */ - FILE_OVERWRITE_IF, /* CREATE_ALWAYS */ - FILE_OPEN, /* OPEN_EXISTING */ - FILE_OPEN_IF, /* OPEN_ALWAYS */ - FILE_OVERWRITE /* TRUNCATE_EXISTING */ - }; - - - /* sanity checks */ - - if (!filename || !filename[0]) - { - SetLastError( ERROR_PATH_NOT_FOUND ); - return INVALID_HANDLE_VALUE; - } - - if (creation < CREATE_NEW || creation > TRUNCATE_EXISTING) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return INVALID_HANDLE_VALUE; - } - - TRACE("%s %s%s%s%s%s%s%s attributes 0x%lx\n", debugstr_w(filename), - (access & GENERIC_READ)?"GENERIC_READ ":"", - (access & GENERIC_WRITE)?"GENERIC_WRITE ":"", - (!access)?"QUERY_ACCESS ":"", - (sharing & FILE_SHARE_READ)?"FILE_SHARE_READ ":"", - (sharing & FILE_SHARE_WRITE)?"FILE_SHARE_WRITE ":"", - (sharing & FILE_SHARE_DELETE)?"FILE_SHARE_DELETE ":"", - creation_name[creation - CREATE_NEW], attributes); - - /* Open a console for CONIN$ or CONOUT$ */ - - if (!strcmpiW(filename, coninW) || !strcmpiW(filename, conoutW)) - { - ret = OpenConsoleW(filename, access, (sa && sa->bInheritHandle), creation); - goto done; - } - - if (!strncmpW(filename, bkslashes_with_dotW, 4)) - { - static const WCHAR pipeW[] = {'P','I','P','E','\\',0}; - - if ((isalphaW(filename[4]) && filename[5] == ':' && filename[6] == '\0') || - !strncmpiW( filename + 4, pipeW, 5 )) - { - dosdev = 0; - } - else if ((dosdev = RtlIsDosDeviceName_U( filename + 4 ))) - { - dosdev += MAKELONG( 0, 4*sizeof(WCHAR) ); /* adjust position to start of filename */ - } - else if (filename[4]) - { - ret = VXD_Open( filename+4, access, sa ); - goto done; - } - else - { - SetLastError( ERROR_INVALID_NAME ); - return INVALID_HANDLE_VALUE; - } - } - else dosdev = RtlIsDosDeviceName_U( filename ); - - if (dosdev) - { - static const WCHAR conW[] = {'C','O','N'}; - - if (LOWORD(dosdev) == sizeof(conW) && - !memicmpW( filename + HIWORD(dosdev)/sizeof(WCHAR), conW, sizeof(conW))) - { - switch (access & (GENERIC_READ|GENERIC_WRITE)) - { - case GENERIC_READ: - ret = OpenConsoleW(coninW, access, (sa && sa->bInheritHandle), creation); - goto done; - case GENERIC_WRITE: - ret = OpenConsoleW(conoutW, access, (sa && sa->bInheritHandle), creation); - goto done; - default: - SetLastError( ERROR_FILE_NOT_FOUND ); - return INVALID_HANDLE_VALUE; - } - } - } - - if (!RtlDosPathNameToNtPathName_U( filename, &nameW, NULL, NULL )) - { - SetLastError( ERROR_PATH_NOT_FOUND ); - return INVALID_HANDLE_VALUE; - } - - /* now call NtCreateFile */ - - options = 0; - if (attributes & FILE_FLAG_BACKUP_SEMANTICS) - options |= FILE_OPEN_FOR_BACKUP_INTENT; - else - options |= FILE_NON_DIRECTORY_FILE; - if (attributes & FILE_FLAG_DELETE_ON_CLOSE) - options |= FILE_DELETE_ON_CLOSE; - if (!(attributes & FILE_FLAG_OVERLAPPED)) - options |= FILE_SYNCHRONOUS_IO_ALERT; - if (attributes & FILE_FLAG_RANDOM_ACCESS) - options |= FILE_RANDOM_ACCESS; - attributes &= FILE_ATTRIBUTE_VALID_FLAGS; - - attr.Length = sizeof(attr); - attr.RootDirectory = 0; - attr.Attributes = OBJ_CASE_INSENSITIVE; - attr.ObjectName = &nameW; - attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL; - attr.SecurityQualityOfService = NULL; - - if (sa && sa->bInheritHandle) attr.Attributes |= OBJ_INHERIT; - - status = NtCreateFile( &ret, access, &attr, &io, NULL, attributes, - sharing, nt_disposition[creation - CREATE_NEW], - options, NULL, 0 ); - if (status) - { - WARN("Unable to create file %s (status %lx)\n", debugstr_w(filename), status); - ret = INVALID_HANDLE_VALUE; - - /* In the case file creation was rejected due to CREATE_NEW flag - * was specified and file with that name already exists, correct - * last error is ERROR_FILE_EXISTS and not ERROR_ALREADY_EXISTS. - * Note: RtlNtStatusToDosError is not the subject to blame here. - */ - if (status == STATUS_OBJECT_NAME_COLLISION) - SetLastError( ERROR_FILE_EXISTS ); - else - SetLastError( RtlNtStatusToDosError(status) ); - } - else SetLastError(0); - RtlFreeUnicodeString( &nameW ); - - done: - if (!ret) ret = INVALID_HANDLE_VALUE; - TRACE("returning %p\n", ret); - return ret; -} - - - -/************************************************************************* - * CreateFileA (KERNEL32.@) - */ -HANDLE WINAPI CreateFileA( LPCSTR filename, DWORD access, DWORD sharing, - LPSECURITY_ATTRIBUTES sa, DWORD creation, - DWORD attributes, HANDLE template) -{ - UNICODE_STRING filenameW; - HANDLE ret = INVALID_HANDLE_VALUE; - - if (!filename) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return INVALID_HANDLE_VALUE; - } - - if (RtlCreateUnicodeStringFromAsciiz(&filenameW, filename)) - { - ret = CreateFileW(filenameW.Buffer, access, sharing, sa, creation, - attributes, template); - RtlFreeUnicodeString(&filenameW); - } - else - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return ret; -} - - -/*********************************************************************** - * GetTempFileNameA (KERNEL32.@) - */ -UINT WINAPI GetTempFileNameA( LPCSTR path, LPCSTR prefix, UINT unique, - LPSTR buffer) -{ - UNICODE_STRING pathW, prefixW; - WCHAR bufferW[MAX_PATH]; - UINT ret; - - if ( !path || !prefix || !buffer ) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return 0; - } - - RtlCreateUnicodeStringFromAsciiz(&pathW, path); - RtlCreateUnicodeStringFromAsciiz(&prefixW, prefix); - - ret = GetTempFileNameW(pathW.Buffer, prefixW.Buffer, unique, bufferW); - if (ret) - WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buffer, MAX_PATH, NULL, NULL); - - RtlFreeUnicodeString(&pathW); - RtlFreeUnicodeString(&prefixW); - return ret; -} - -/*********************************************************************** - * GetTempFileNameW (KERNEL32.@) - */ -UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique, - LPWSTR buffer ) -{ - static const WCHAR formatW[] = {'%','x','.','t','m','p',0}; - - int i; - LPWSTR p; - - if ( !path || !prefix || !buffer ) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return 0; - } - - strcpyW( buffer, path ); - p = buffer + strlenW(buffer); - - /* add a \, if there isn't one */ - if ((p == buffer) || (p[-1] != '\\')) *p++ = '\\'; - - for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++; - - unique &= 0xffff; - - if (unique) sprintfW( p, formatW, unique ); - else - { - /* get a "random" unique number and try to create the file */ - HANDLE handle; - UINT num = GetTickCount() & 0xffff; - - if (!num) num = 1; - unique = num; - do - { - sprintfW( p, formatW, unique ); - handle = CreateFileW( buffer, GENERIC_WRITE, 0, NULL, - CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 ); - if (handle != INVALID_HANDLE_VALUE) - { /* We created it */ - TRACE("created %s\n", debugstr_w(buffer) ); - CloseHandle( handle ); - break; - } - if (GetLastError() != ERROR_FILE_EXISTS && - GetLastError() != ERROR_SHARING_VIOLATION) - break; /* No need to go on */ - if (!(++unique & 0xffff)) unique = 1; - } while (unique != num); - } - - TRACE("returning %s\n", debugstr_w(buffer) ); - return unique; -} - - -/****************************************************************** - * FILE_ReadWriteApc (internal) - * - * - */ -static void WINAPI FILE_ReadWriteApc(void* apc_user, PIO_STATUS_BLOCK io_status, ULONG len) -{ - LPOVERLAPPED_COMPLETION_ROUTINE cr = (LPOVERLAPPED_COMPLETION_ROUTINE)apc_user; - - cr(RtlNtStatusToDosError(io_status->u.Status), len, (LPOVERLAPPED)io_status); -} - -/*********************************************************************** - * ReadFileEx (KERNEL32.@) - */ -BOOL WINAPI ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, - LPOVERLAPPED overlapped, - LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) -{ - LARGE_INTEGER offset; - NTSTATUS status; - PIO_STATUS_BLOCK io_status; - - if (!overlapped) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - offset.u.LowPart = overlapped->Offset; - offset.u.HighPart = overlapped->OffsetHigh; - io_status = (PIO_STATUS_BLOCK)overlapped; - io_status->u.Status = STATUS_PENDING; - - status = NtReadFile(hFile, NULL, FILE_ReadWriteApc, lpCompletionRoutine, - io_status, buffer, bytesToRead, &offset, NULL); - - if (status) - { - SetLastError( RtlNtStatusToDosError(status) ); - return FALSE; - } - return TRUE; -} - -/*********************************************************************** - * ReadFile (KERNEL32.@) - */ -BOOL WINAPI ReadFile( HANDLE hFile, LPVOID buffer, DWORD bytesToRead, - LPDWORD bytesRead, LPOVERLAPPED overlapped ) -{ - LARGE_INTEGER offset; - PLARGE_INTEGER poffset = NULL; - IO_STATUS_BLOCK iosb; - PIO_STATUS_BLOCK io_status = &iosb; - HANDLE hEvent = 0; - NTSTATUS status; - - TRACE("%p %p %ld %p %p\n", hFile, buffer, bytesToRead, - bytesRead, overlapped ); - - if (bytesRead) *bytesRead = 0; /* Do this before anything else */ - if (!bytesToRead) return TRUE; - - if (IsBadReadPtr(buffer, bytesToRead)) - { - SetLastError(ERROR_WRITE_FAULT); /* FIXME */ - return FALSE; - } - if (is_console_handle(hFile)) - return ReadConsoleA(hFile, buffer, bytesToRead, bytesRead, NULL); - - if (overlapped != NULL) - { - offset.u.LowPart = overlapped->Offset; - offset.u.HighPart = overlapped->OffsetHigh; - poffset = &offset; - hEvent = overlapped->hEvent; - io_status = (PIO_STATUS_BLOCK)overlapped; - } - io_status->u.Status = STATUS_PENDING; - io_status->Information = 0; - - status = NtReadFile(hFile, hEvent, NULL, NULL, io_status, buffer, bytesToRead, poffset, NULL); - - if (status != STATUS_PENDING && bytesRead) - *bytesRead = io_status->Information; - - if (status && status != STATUS_END_OF_FILE) - { - SetLastError( RtlNtStatusToDosError(status) ); - return FALSE; - } - return TRUE; -} - - -/*********************************************************************** - * WriteFileEx (KERNEL32.@) - */ -BOOL WINAPI WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite, - LPOVERLAPPED overlapped, - LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) -{ - LARGE_INTEGER offset; - NTSTATUS status; - PIO_STATUS_BLOCK io_status; - - TRACE("%p %p %ld %p %p\n", - hFile, buffer, bytesToWrite, overlapped, lpCompletionRoutine); - - if (overlapped == NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - offset.u.LowPart = overlapped->Offset; - offset.u.HighPart = overlapped->OffsetHigh; - - io_status = (PIO_STATUS_BLOCK)overlapped; - io_status->u.Status = STATUS_PENDING; - - status = NtWriteFile(hFile, NULL, FILE_ReadWriteApc, lpCompletionRoutine, - io_status, buffer, bytesToWrite, &offset, NULL); - - if (status) SetLastError( RtlNtStatusToDosError(status) ); - return !status; -} - -/*********************************************************************** - * WriteFile (KERNEL32.@) - */ -BOOL WINAPI WriteFile( HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite, - LPDWORD bytesWritten, LPOVERLAPPED overlapped ) -{ - HANDLE hEvent = NULL; - LARGE_INTEGER offset; - PLARGE_INTEGER poffset = NULL; - NTSTATUS status; - IO_STATUS_BLOCK iosb; - PIO_STATUS_BLOCK piosb = &iosb; - - TRACE("%p %p %ld %p %p\n", - hFile, buffer, bytesToWrite, bytesWritten, overlapped ); - - if (is_console_handle(hFile)) - return WriteConsoleA(hFile, buffer, bytesToWrite, bytesWritten, NULL); - - if (IsBadReadPtr(buffer, bytesToWrite)) - { - SetLastError(ERROR_READ_FAULT); /* FIXME */ - return FALSE; - } - - if (overlapped) - { - offset.u.LowPart = overlapped->Offset; - offset.u.HighPart = overlapped->OffsetHigh; - poffset = &offset; - hEvent = overlapped->hEvent; - piosb = (PIO_STATUS_BLOCK)overlapped; - } - piosb->u.Status = STATUS_PENDING; - piosb->Information = 0; - - status = NtWriteFile(hFile, hEvent, NULL, NULL, piosb, - buffer, bytesToWrite, poffset, NULL); - if (status) - { - SetLastError( RtlNtStatusToDosError(status) ); - return FALSE; - } - if (bytesWritten) *bytesWritten = piosb->Information; - - return TRUE; -} - - -/*********************************************************************** - * SetFilePointer (KERNEL32.@) - */ -DWORD WINAPI SetFilePointer( HANDLE hFile, LONG distance, LONG *highword, - DWORD method ) -{ - static const int whence[3] = { SEEK_SET, SEEK_CUR, SEEK_END }; - DWORD ret = INVALID_SET_FILE_POINTER; - NTSTATUS status; - int fd; - - TRACE("handle %p offset %ld high %ld origin %ld\n", - hFile, distance, highword?*highword:0, method ); - - if (method > FILE_END) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return ret; - } - - if (!(status = wine_server_handle_to_fd( hFile, 0, &fd, NULL, NULL ))) - { - off_t pos, res; - - if (highword) pos = ((off_t)*highword << 32) | (ULONG)distance; - else pos = (off_t)distance; - if ((res = lseek( fd, pos, whence[method] )) == (off_t)-1) - { - /* also check EPERM due to SuSE7 2.2.16 lseek() EPERM kernel bug */ - if (((errno == EINVAL) || (errno == EPERM)) && (method != FILE_BEGIN) && (pos < 0)) - SetLastError( ERROR_NEGATIVE_SEEK ); - else - FILE_SetDosError(); - } - else - { - ret = (DWORD)res; - if (highword) *highword = (res >> 32); - if (ret == INVALID_SET_FILE_POINTER) SetLastError( 0 ); - } - wine_server_release_fd( hFile, fd ); - } - else SetLastError( RtlNtStatusToDosError(status) ); - - return ret; -} - - -/************************************************************************* - * SetHandleCount (KERNEL32.@) - */ -UINT WINAPI SetHandleCount( UINT count ) -{ - return min( 256, count ); -} - - -/************************************************************************** - * CopyFileW (KERNEL32.@) - */ -BOOL WINAPI CopyFileW( LPCWSTR source, LPCWSTR dest, BOOL fail_if_exists ) -{ - HANDLE h1, h2; - BY_HANDLE_FILE_INFORMATION info; - DWORD count; - BOOL ret = FALSE; - char buffer[2048]; - - if (!source || !dest) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - TRACE("%s -> %s\n", debugstr_w(source), debugstr_w(dest)); - - if ((h1 = CreateFileW(source, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) - { - WARN("Unable to open source %s\n", debugstr_w(source)); - return FALSE; - } - - if (!GetFileInformationByHandle( h1, &info )) - { - WARN("GetFileInformationByHandle returned error for %s\n", debugstr_w(source)); - CloseHandle( h1 ); - return FALSE; - } - - if ((h2 = CreateFileW( dest, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, - fail_if_exists ? CREATE_NEW : CREATE_ALWAYS, - info.dwFileAttributes, h1 )) == INVALID_HANDLE_VALUE) - { - WARN("Unable to open dest %s\n", debugstr_w(dest)); - CloseHandle( h1 ); - return FALSE; - } - - while (ReadFile( h1, buffer, sizeof(buffer), &count, NULL ) && count) - { - char *p = buffer; - while (count != 0) - { - DWORD res; - if (!WriteFile( h2, p, count, &res, NULL ) || !res) goto done; - p += res; - count -= res; - } - } - ret = TRUE; -done: - CloseHandle( h1 ); - CloseHandle( h2 ); - return ret; -} - - -/************************************************************************** - * CopyFileA (KERNEL32.@) - */ -BOOL WINAPI CopyFileA( LPCSTR source, LPCSTR dest, BOOL fail_if_exists) -{ - UNICODE_STRING sourceW, destW; - BOOL ret; - - if (!source || !dest) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - RtlCreateUnicodeStringFromAsciiz(&sourceW, source); - RtlCreateUnicodeStringFromAsciiz(&destW, dest); - - ret = CopyFileW(sourceW.Buffer, destW.Buffer, fail_if_exists); - - RtlFreeUnicodeString(&sourceW); - RtlFreeUnicodeString(&destW); - return ret; -} - - -/************************************************************************** - * CopyFileExW (KERNEL32.@) - * - * This implementation ignores most of the extra parameters passed-in into - * the "ex" version of the method and calls the CopyFile method. - * It will have to be fixed eventually. - */ -BOOL WINAPI CopyFileExW(LPCWSTR sourceFilename, LPCWSTR destFilename, - LPPROGRESS_ROUTINE progressRoutine, LPVOID appData, - LPBOOL cancelFlagPointer, DWORD copyFlags) -{ - /* - * Interpret the only flag that CopyFile can interpret. - */ - return CopyFileW(sourceFilename, destFilename, (copyFlags & COPY_FILE_FAIL_IF_EXISTS) != 0); -} - - -/************************************************************************** - * CopyFileExA (KERNEL32.@) - */ -BOOL WINAPI CopyFileExA(LPCSTR sourceFilename, LPCSTR destFilename, - LPPROGRESS_ROUTINE progressRoutine, LPVOID appData, - LPBOOL cancelFlagPointer, DWORD copyFlags) -{ - UNICODE_STRING sourceW, destW; - BOOL ret; - - if (!sourceFilename || !destFilename) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - RtlCreateUnicodeStringFromAsciiz(&sourceW, sourceFilename); - RtlCreateUnicodeStringFromAsciiz(&destW, destFilename); - - ret = CopyFileExW(sourceW.Buffer, destW.Buffer, progressRoutine, appData, - cancelFlagPointer, copyFlags); - - RtlFreeUnicodeString(&sourceW); - RtlFreeUnicodeString(&destW); - return ret; -} diff --git a/files/smb.c b/files/smb.c index 866629a9e4..0518d20b14 100644 --- a/files/smb.c +++ b/files/smb.c @@ -111,7 +111,6 @@ #include "winreg.h" #include "winternl.h" #include "lmerr.h" -#include "file.h" #include "smb.h" #include "wine/server.h" diff --git a/include/file.h b/include/file.h deleted file mode 100644 index b234399554..0000000000 --- a/include/file.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * File handling declarations - * - * Copyright 1996 Alexandre Julliard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __WINE_FILE_H -#define __WINE_FILE_H - -#include -#include -#include - -#define MAX_PATHNAME_LEN 1024 - -/* files/file.c */ -extern void FILE_SetDosError(void); - -/* files/directory.c */ -extern int DIR_Init(void); - -/* vxd.c */ -extern HANDLE VXD_Open( LPCWSTR filename, DWORD access, LPSECURITY_ATTRIBUTES sa ); - -#endif /* __WINE_FILE_H */ diff --git a/misc/registry.c b/misc/registry.c index 1c8d4e208b..51aed28731 100644 --- a/misc/registry.c +++ b/misc/registry.c @@ -70,7 +70,6 @@ #include "wine/library.h" #include "wine/server.h" #include "wine/unicode.h" -#include "file.h" #include "wine/debug.h" @@ -84,6 +83,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(reg); #define SAVE_LOCAL_REGBRANCH_USER_DEFAULT "userdef.reg" #define SAVE_LOCAL_REGBRANCH_LOCAL_MACHINE "system.reg" +#define MAX_PATHNAME_LEN 1024 + static const WCHAR ClassesRootW[] = {'M','a','c','h','i','n','e','\\', 'S','o','f','t','w','a','r','e','\\', 'C','l','a','s','s','e','s',0};