ntdll: Move a few file functions to the Unix library.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
e0fca94511
commit
9ed9512662
|
@ -215,28 +215,6 @@ void init_directories(void)
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DIR_is_hidden_file
|
||||
*
|
||||
* Check if the specified file should be hidden based on its name and the show dot files option.
|
||||
*/
|
||||
BOOL DIR_is_hidden_file( const UNICODE_STRING *name )
|
||||
{
|
||||
WCHAR *p, *end;
|
||||
|
||||
if (show_dot_files) return FALSE;
|
||||
|
||||
end = p = name->Buffer + name->Length/sizeof(WCHAR);
|
||||
while (p > name->Buffer && IS_SEPARATOR(p[-1])) p--;
|
||||
while (p > name->Buffer && !IS_SEPARATOR(p[-1])) p--;
|
||||
if (p == end || *p != '.') return FALSE;
|
||||
/* make sure it isn't '.' or '..' */
|
||||
if (p + 1 == end) return FALSE;
|
||||
if (p[1] == '.' && p + 2 == end) return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* NtQueryDirectoryFile [NTDLL.@]
|
||||
* ZwQueryDirectoryFile [NTDLL.@]
|
||||
|
|
|
@ -111,7 +111,6 @@
|
|||
#include "ddk/mountmgr.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(winediag);
|
||||
|
||||
mode_t FILE_umask = 0;
|
||||
|
||||
|
@ -157,8 +156,7 @@ int fd_get_file_info( int fd, unsigned int options, struct stat *st, ULONG *attr
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* get the stat info and file attributes for a file (by name) */
|
||||
int get_file_info( const char *path, struct stat *st, ULONG *attr )
|
||||
static int get_file_info( const char *path, struct stat *st, ULONG *attr )
|
||||
{
|
||||
char *parent_path;
|
||||
int ret;
|
||||
|
@ -190,121 +188,6 @@ int get_file_info( const char *path, struct stat *st, ULONG *attr )
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* FILE_CreateFile (internal)
|
||||
* Open a file.
|
||||
*
|
||||
* Parameter set fully identical with NtCreateFile
|
||||
*/
|
||||
static NTSTATUS FILE_CreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIBUTES attr,
|
||||
PIO_STATUS_BLOCK io, PLARGE_INTEGER alloc_size,
|
||||
ULONG attributes, ULONG sharing, ULONG disposition,
|
||||
ULONG options, PVOID ea_buffer, ULONG ea_length )
|
||||
{
|
||||
ANSI_STRING unix_name;
|
||||
BOOL created = FALSE;
|
||||
|
||||
TRACE("handle=%p access=%08x name=%s objattr=%08x root=%p sec=%p io=%p alloc_size=%p "
|
||||
"attr=%08x sharing=%08x disp=%d options=%08x ea=%p.0x%08x\n",
|
||||
handle, access, debugstr_us(attr->ObjectName), attr->Attributes,
|
||||
attr->RootDirectory, attr->SecurityDescriptor, io, alloc_size,
|
||||
attributes, sharing, disposition, options, ea_buffer, ea_length );
|
||||
|
||||
if (!attr || !attr->ObjectName) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
if (alloc_size) FIXME( "alloc_size not supported\n" );
|
||||
|
||||
if (options & FILE_OPEN_BY_FILE_ID)
|
||||
io->u.Status = unix_funcs->file_id_to_unix_file_name( attr, &unix_name );
|
||||
else
|
||||
io->u.Status = unix_funcs->nt_to_unix_file_name_attr( attr, &unix_name, disposition );
|
||||
|
||||
if (io->u.Status == STATUS_BAD_DEVICE_TYPE)
|
||||
{
|
||||
SERVER_START_REQ( open_file_object )
|
||||
{
|
||||
req->access = access;
|
||||
req->attributes = attr->Attributes;
|
||||
req->rootdir = wine_server_obj_handle( attr->RootDirectory );
|
||||
req->sharing = sharing;
|
||||
req->options = options;
|
||||
wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
|
||||
io->u.Status = wine_server_call( req );
|
||||
*handle = wine_server_ptr_handle( reply->handle );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (io->u.Status == STATUS_SUCCESS) io->Information = FILE_OPENED;
|
||||
return io->u.Status;
|
||||
}
|
||||
|
||||
if (io->u.Status == STATUS_NO_SUCH_FILE &&
|
||||
disposition != FILE_OPEN && disposition != FILE_OVERWRITE)
|
||||
{
|
||||
created = TRUE;
|
||||
io->u.Status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (io->u.Status == STATUS_SUCCESS)
|
||||
{
|
||||
static UNICODE_STRING empty_string;
|
||||
OBJECT_ATTRIBUTES unix_attr = *attr;
|
||||
data_size_t len;
|
||||
struct object_attributes *objattr;
|
||||
|
||||
unix_attr.ObjectName = &empty_string; /* we send the unix name instead */
|
||||
if ((io->u.Status = alloc_object_attributes( &unix_attr, &objattr, &len )))
|
||||
{
|
||||
RtlFreeAnsiString( &unix_name );
|
||||
return io->u.Status;
|
||||
}
|
||||
|
||||
SERVER_START_REQ( create_file )
|
||||
{
|
||||
req->access = access;
|
||||
req->sharing = sharing;
|
||||
req->create = disposition;
|
||||
req->options = options;
|
||||
req->attrs = attributes;
|
||||
wine_server_add_data( req, objattr, len );
|
||||
wine_server_add_data( req, unix_name.Buffer, unix_name.Length );
|
||||
io->u.Status = wine_server_call( req );
|
||||
*handle = wine_server_ptr_handle( reply->handle );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
RtlFreeHeap( GetProcessHeap(), 0, objattr );
|
||||
RtlFreeAnsiString( &unix_name );
|
||||
}
|
||||
else WARN("%s not found (%x)\n", debugstr_us(attr->ObjectName), io->u.Status );
|
||||
|
||||
if (io->u.Status == STATUS_SUCCESS)
|
||||
{
|
||||
if (created) io->Information = FILE_CREATED;
|
||||
else switch(disposition)
|
||||
{
|
||||
case FILE_SUPERSEDE:
|
||||
io->Information = FILE_SUPERSEDED;
|
||||
break;
|
||||
case FILE_CREATE:
|
||||
io->Information = FILE_CREATED;
|
||||
break;
|
||||
case FILE_OPEN:
|
||||
case FILE_OPEN_IF:
|
||||
io->Information = FILE_OPENED;
|
||||
break;
|
||||
case FILE_OVERWRITE:
|
||||
case FILE_OVERWRITE_IF:
|
||||
io->Information = FILE_OVERWRITTEN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (io->u.Status == STATUS_TOO_MANY_OPENED_FILES)
|
||||
{
|
||||
static int once;
|
||||
if (!once++) ERR_(winediag)( "Too many open files, ulimit -n probably needs to be increased\n" );
|
||||
}
|
||||
|
||||
return io->u.Status;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* NtOpenFile [NTDLL.@]
|
||||
|
@ -328,8 +211,7 @@ NTSTATUS WINAPI NtOpenFile( PHANDLE handle, ACCESS_MASK access,
|
|||
POBJECT_ATTRIBUTES attr, PIO_STATUS_BLOCK io,
|
||||
ULONG sharing, ULONG options )
|
||||
{
|
||||
return FILE_CreateFile( handle, access, attr, io, NULL, 0,
|
||||
sharing, FILE_OPEN, options, NULL, 0 );
|
||||
return unix_funcs->NtOpenFile( handle, access, attr, io, sharing, options );
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -361,8 +243,8 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIB
|
|||
ULONG attributes, ULONG sharing, ULONG disposition,
|
||||
ULONG options, PVOID ea_buffer, ULONG ea_length )
|
||||
{
|
||||
return FILE_CreateFile( handle, access, attr, io, alloc_size, attributes,
|
||||
sharing, disposition, options, ea_buffer, ea_length );
|
||||
return unix_funcs->NtCreateFile( handle, access, attr, io, alloc_size, attributes,
|
||||
sharing, disposition, options, ea_buffer, ea_length );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -3002,40 +2884,7 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
|
|||
NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr,
|
||||
FILE_NETWORK_OPEN_INFORMATION *info )
|
||||
{
|
||||
ANSI_STRING unix_name;
|
||||
NTSTATUS status;
|
||||
|
||||
if (!(status = unix_funcs->nt_to_unix_file_name_attr( attr, &unix_name, FILE_OPEN )))
|
||||
{
|
||||
ULONG attributes;
|
||||
struct stat st;
|
||||
|
||||
if (get_file_info( unix_name.Buffer, &st, &attributes ) == -1)
|
||||
status = FILE_GetNtStatus();
|
||||
else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
|
||||
status = STATUS_INVALID_INFO_CLASS;
|
||||
else
|
||||
{
|
||||
FILE_BASIC_INFORMATION basic;
|
||||
FILE_STANDARD_INFORMATION std;
|
||||
|
||||
fill_file_info( &st, attributes, &basic, FileBasicInformation );
|
||||
fill_file_info( &st, attributes, &std, FileStandardInformation );
|
||||
|
||||
info->CreationTime = basic.CreationTime;
|
||||
info->LastAccessTime = basic.LastAccessTime;
|
||||
info->LastWriteTime = basic.LastWriteTime;
|
||||
info->ChangeTime = basic.ChangeTime;
|
||||
info->AllocationSize = std.AllocationSize;
|
||||
info->EndOfFile = std.EndOfFile;
|
||||
info->FileAttributes = basic.FileAttributes;
|
||||
if (DIR_is_hidden_file( attr->ObjectName ))
|
||||
info->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
|
||||
}
|
||||
RtlFreeAnsiString( &unix_name );
|
||||
}
|
||||
else WARN("%s not found (%x)\n", debugstr_us(attr->ObjectName), status );
|
||||
return status;
|
||||
return unix_funcs->NtQueryFullAttributesFile( attr, info );
|
||||
}
|
||||
|
||||
|
||||
|
@ -3045,28 +2894,7 @@ NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr,
|
|||
*/
|
||||
NTSTATUS WINAPI NtQueryAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_BASIC_INFORMATION *info )
|
||||
{
|
||||
ANSI_STRING unix_name;
|
||||
NTSTATUS status;
|
||||
|
||||
if (!(status = unix_funcs->nt_to_unix_file_name_attr( attr, &unix_name, FILE_OPEN )))
|
||||
{
|
||||
ULONG attributes;
|
||||
struct stat st;
|
||||
|
||||
if (get_file_info( unix_name.Buffer, &st, &attributes ) == -1)
|
||||
status = FILE_GetNtStatus();
|
||||
else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
|
||||
status = STATUS_INVALID_INFO_CLASS;
|
||||
else
|
||||
{
|
||||
status = fill_file_info( &st, attributes, info, FileBasicInformation );
|
||||
if (DIR_is_hidden_file( attr->ObjectName ))
|
||||
info->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
|
||||
}
|
||||
RtlFreeAnsiString( &unix_name );
|
||||
}
|
||||
else WARN("%s not found (%x)\n", debugstr_us(attr->ObjectName), status );
|
||||
return status;
|
||||
return unix_funcs->NtQueryAttributesFile( attr, info );
|
||||
}
|
||||
|
||||
|
||||
|
@ -3732,75 +3560,26 @@ NTSTATUS WINAPI NtUnlockFile( HANDLE hFile, PIO_STATUS_BLOCK io_status,
|
|||
|
||||
/******************************************************************
|
||||
* NtCreateNamedPipeFile (NTDLL.@)
|
||||
*
|
||||
*
|
||||
*/
|
||||
NTSTATUS WINAPI NtCreateNamedPipeFile( PHANDLE handle, ULONG access,
|
||||
POBJECT_ATTRIBUTES attr, PIO_STATUS_BLOCK iosb,
|
||||
ULONG sharing, ULONG dispo, ULONG options,
|
||||
ULONG pipe_type, ULONG read_mode,
|
||||
ULONG pipe_type, ULONG read_mode,
|
||||
ULONG completion_mode, ULONG max_inst,
|
||||
ULONG inbound_quota, ULONG outbound_quota,
|
||||
PLARGE_INTEGER timeout)
|
||||
{
|
||||
NTSTATUS status;
|
||||
data_size_t len;
|
||||
struct object_attributes *objattr;
|
||||
|
||||
if (!attr) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
TRACE("(%p %x %s %p %x %d %x %d %d %d %d %d %d %p)\n",
|
||||
handle, access, debugstr_us(attr->ObjectName), iosb, sharing, dispo,
|
||||
options, pipe_type, read_mode, completion_mode, max_inst, inbound_quota,
|
||||
outbound_quota, timeout);
|
||||
|
||||
/* assume we only get relative timeout */
|
||||
if (timeout->QuadPart > 0)
|
||||
FIXME("Wrong time %s\n", wine_dbgstr_longlong(timeout->QuadPart));
|
||||
|
||||
if ((status = alloc_object_attributes( attr, &objattr, &len ))) return status;
|
||||
|
||||
SERVER_START_REQ( create_named_pipe )
|
||||
{
|
||||
req->access = access;
|
||||
req->options = options;
|
||||
req->sharing = sharing;
|
||||
req->flags =
|
||||
(pipe_type ? NAMED_PIPE_MESSAGE_STREAM_WRITE : 0) |
|
||||
(read_mode ? NAMED_PIPE_MESSAGE_STREAM_READ : 0) |
|
||||
(completion_mode ? NAMED_PIPE_NONBLOCKING_MODE : 0);
|
||||
req->maxinstances = max_inst;
|
||||
req->outsize = outbound_quota;
|
||||
req->insize = inbound_quota;
|
||||
req->timeout = timeout->QuadPart;
|
||||
wine_server_add_data( req, objattr, len );
|
||||
status = wine_server_call( req );
|
||||
if (!status) *handle = wine_server_ptr_handle( reply->handle );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
RtlFreeHeap( GetProcessHeap(), 0, objattr );
|
||||
return status;
|
||||
return unix_funcs->NtCreateNamedPipeFile( handle, access, attr, iosb, sharing, dispo, options,
|
||||
pipe_type, read_mode, completion_mode, max_inst,
|
||||
inbound_quota, outbound_quota, timeout );
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* NtDeleteFile (NTDLL.@)
|
||||
*
|
||||
*
|
||||
*/
|
||||
NTSTATUS WINAPI NtDeleteFile( POBJECT_ATTRIBUTES ObjectAttributes )
|
||||
NTSTATUS WINAPI NtDeleteFile( OBJECT_ATTRIBUTES *attr )
|
||||
{
|
||||
NTSTATUS status;
|
||||
HANDLE hFile;
|
||||
IO_STATUS_BLOCK io;
|
||||
|
||||
TRACE("%p\n", ObjectAttributes);
|
||||
status = NtCreateFile( &hFile, GENERIC_READ | GENERIC_WRITE | DELETE,
|
||||
ObjectAttributes, &io, NULL, 0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
FILE_OPEN, FILE_DELETE_ON_CLOSE, NULL, 0 );
|
||||
if (status == STATUS_SUCCESS) status = NtClose(hFile);
|
||||
return status;
|
||||
return unix_funcs->NtDeleteFile( attr );
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
|
@ -3848,59 +3627,10 @@ NTSTATUS WINAPI NtCancelIoFile( HANDLE hFile, PIO_STATUS_BLOCK io_status )
|
|||
/******************************************************************************
|
||||
* NtCreateMailslotFile [NTDLL.@]
|
||||
* ZwCreateMailslotFile [NTDLL.@]
|
||||
*
|
||||
* PARAMS
|
||||
* pHandle [O] pointer to receive the handle created
|
||||
* DesiredAccess [I] access mode (read, write, etc)
|
||||
* ObjectAttributes [I] fully qualified NT path of the mailslot
|
||||
* IoStatusBlock [O] receives completion status and other info
|
||||
* CreateOptions [I]
|
||||
* MailslotQuota [I]
|
||||
* MaxMessageSize [I]
|
||||
* TimeOut [I]
|
||||
*
|
||||
* RETURNS
|
||||
* An NT status code
|
||||
*/
|
||||
NTSTATUS WINAPI NtCreateMailslotFile(PHANDLE pHandle, ULONG DesiredAccess,
|
||||
POBJECT_ATTRIBUTES attr, PIO_STATUS_BLOCK IoStatusBlock,
|
||||
ULONG CreateOptions, ULONG MailslotQuota, ULONG MaxMessageSize,
|
||||
PLARGE_INTEGER TimeOut)
|
||||
NTSTATUS WINAPI NtCreateMailslotFile( HANDLE *handle, ULONG access, OBJECT_ATTRIBUTES *attr,
|
||||
IO_STATUS_BLOCK *io, ULONG options, ULONG quota, ULONG msg_size,
|
||||
LARGE_INTEGER *timeout )
|
||||
{
|
||||
LARGE_INTEGER timeout;
|
||||
NTSTATUS ret;
|
||||
data_size_t len;
|
||||
struct object_attributes *objattr;
|
||||
|
||||
TRACE("%p %08x %p %p %08x %08x %08x %p\n",
|
||||
pHandle, DesiredAccess, attr, IoStatusBlock,
|
||||
CreateOptions, MailslotQuota, MaxMessageSize, TimeOut);
|
||||
|
||||
if (!pHandle) return STATUS_ACCESS_VIOLATION;
|
||||
if (!attr) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
|
||||
|
||||
/*
|
||||
* For a NULL TimeOut pointer set the default timeout value
|
||||
*/
|
||||
if (!TimeOut)
|
||||
timeout.QuadPart = -1;
|
||||
else
|
||||
timeout.QuadPart = TimeOut->QuadPart;
|
||||
|
||||
SERVER_START_REQ( create_mailslot )
|
||||
{
|
||||
req->access = DesiredAccess;
|
||||
req->max_msgsize = MaxMessageSize;
|
||||
req->read_timeout = timeout.QuadPart;
|
||||
wine_server_add_data( req, objattr, len );
|
||||
ret = wine_server_call( req );
|
||||
if( ret == STATUS_SUCCESS )
|
||||
*pHandle = wine_server_ptr_handle( reply->handle );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
RtlFreeHeap( GetProcessHeap(), 0, objattr );
|
||||
return ret;
|
||||
return unix_funcs->NtCreateMailslotFile( handle, access, attr, io, options, quota, msg_size, timeout );
|
||||
}
|
||||
|
|
|
@ -139,14 +139,9 @@ extern NTSTATUS TAPE_DeviceIoControl(HANDLE hDevice,
|
|||
extern NTSTATUS COMM_FlushBuffersFile( int fd ) DECLSPEC_HIDDEN;
|
||||
|
||||
/* file I/O */
|
||||
struct stat;
|
||||
extern NTSTATUS FILE_GetNtStatus(void) DECLSPEC_HIDDEN;
|
||||
extern int get_file_info( const char *path, struct stat *st, ULONG *attr ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS fill_file_info( const struct stat *st, ULONG attr, void *ptr,
|
||||
FILE_INFORMATION_CLASS class ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS server_get_unix_name( HANDLE handle, ANSI_STRING *unix_name ) DECLSPEC_HIDDEN;
|
||||
extern void init_directories(void) DECLSPEC_HIDDEN;
|
||||
extern BOOL DIR_is_hidden_file( const UNICODE_STRING *name ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS DIR_get_unix_cwd( char **cwd ) DECLSPEC_HIDDEN;
|
||||
extern unsigned int DIR_get_drives_info( struct drive_info info[MAX_DOS_DRIVES] ) DECLSPEC_HIDDEN;
|
||||
|
||||
|
|
|
@ -111,6 +111,7 @@
|
|||
#include "unix_private.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(file);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(winediag);
|
||||
|
||||
#define MAX_DOS_DRIVES 26
|
||||
|
||||
|
@ -312,6 +313,48 @@ static inline BOOL has_wildcard( const UNICODE_STRING *mask )
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static NTSTATUS errno_to_status( int err )
|
||||
{
|
||||
TRACE( "errno = %d\n", err );
|
||||
switch (err)
|
||||
{
|
||||
case EAGAIN: return STATUS_SHARING_VIOLATION;
|
||||
case EBADF: return STATUS_INVALID_HANDLE;
|
||||
case EBUSY: return STATUS_DEVICE_BUSY;
|
||||
case ENOSPC: return STATUS_DISK_FULL;
|
||||
case EPERM:
|
||||
case EROFS:
|
||||
case EACCES: return STATUS_ACCESS_DENIED;
|
||||
case ENOTDIR: return STATUS_OBJECT_PATH_NOT_FOUND;
|
||||
case ENOENT: return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
case EISDIR: return STATUS_FILE_IS_A_DIRECTORY;
|
||||
case EMFILE:
|
||||
case ENFILE: return STATUS_TOO_MANY_OPENED_FILES;
|
||||
case EINVAL: return STATUS_INVALID_PARAMETER;
|
||||
case ENOTEMPTY: return STATUS_DIRECTORY_NOT_EMPTY;
|
||||
case EPIPE: return STATUS_PIPE_DISCONNECTED;
|
||||
case EIO: return STATUS_DEVICE_NOT_READY;
|
||||
#ifdef ENOMEDIUM
|
||||
case ENOMEDIUM: return STATUS_NO_MEDIA_IN_DEVICE;
|
||||
#endif
|
||||
case ENXIO: return STATUS_NO_SUCH_DEVICE;
|
||||
case ENOTTY:
|
||||
case EOPNOTSUPP:return STATUS_NOT_SUPPORTED;
|
||||
case ECONNRESET:return STATUS_PIPE_DISCONNECTED;
|
||||
case EFAULT: return STATUS_ACCESS_VIOLATION;
|
||||
case ESPIPE: return STATUS_ILLEGAL_FUNCTION;
|
||||
case ELOOP: return STATUS_REPARSE_POINT_NOT_RESOLVED;
|
||||
#ifdef ETIME /* Missing on FreeBSD */
|
||||
case ETIME: return STATUS_IO_TIMEOUT;
|
||||
#endif
|
||||
case ENOEXEC: /* ?? */
|
||||
case EEXIST: /* ?? */
|
||||
default:
|
||||
FIXME( "Converting errno %d to STATUS_UNSUCCESSFUL\n", err );
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
|
||||
/* get space from the current directory data buffer, allocating a new one if necessary */
|
||||
static void *get_dir_data_space( struct dir_data *data, unsigned int size )
|
||||
{
|
||||
|
@ -1169,6 +1212,28 @@ static BOOLEAN get_dir_case_sensitivity( const char *dir )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* is_hidden_file
|
||||
*
|
||||
* Check if the specified file should be hidden based on its name and the show dot files option.
|
||||
*/
|
||||
static BOOL is_hidden_file( const UNICODE_STRING *name )
|
||||
{
|
||||
WCHAR *p, *end;
|
||||
|
||||
if (show_dot_files) return FALSE;
|
||||
|
||||
end = p = name->Buffer + name->Length/sizeof(WCHAR);
|
||||
while (p > name->Buffer && IS_SEPARATOR(p[-1])) p--;
|
||||
while (p > name->Buffer && !IS_SEPARATOR(p[-1])) p--;
|
||||
if (p == end || *p != '.') return FALSE;
|
||||
/* make sure it isn't '.' or '..' */
|
||||
if (p + 1 == end) return FALSE;
|
||||
if (p[1] == '.' && p + 2 == end) return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* hash_short_file_name
|
||||
*
|
||||
|
@ -2925,3 +2990,295 @@ void CDECL set_show_dot_files( BOOL enable )
|
|||
{
|
||||
show_dot_files = enable;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* NtCreateFile (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtCreateFile( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr,
|
||||
IO_STATUS_BLOCK *io, LARGE_INTEGER *alloc_size,
|
||||
ULONG attributes, ULONG sharing, ULONG disposition,
|
||||
ULONG options, void *ea_buffer, ULONG ea_length )
|
||||
{
|
||||
ANSI_STRING unix_name;
|
||||
BOOL created = FALSE;
|
||||
|
||||
TRACE( "handle=%p access=%08x name=%s objattr=%08x root=%p sec=%p io=%p alloc_size=%p "
|
||||
"attr=%08x sharing=%08x disp=%d options=%08x ea=%p.0x%08x\n",
|
||||
handle, access, debugstr_us(attr->ObjectName), attr->Attributes,
|
||||
attr->RootDirectory, attr->SecurityDescriptor, io, alloc_size,
|
||||
attributes, sharing, disposition, options, ea_buffer, ea_length );
|
||||
|
||||
if (!attr || !attr->ObjectName) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
if (alloc_size) FIXME( "alloc_size not supported\n" );
|
||||
|
||||
if (options & FILE_OPEN_BY_FILE_ID)
|
||||
io->u.Status = file_id_to_unix_file_name( attr, &unix_name );
|
||||
else
|
||||
io->u.Status = nt_to_unix_file_name_attr( attr, &unix_name, disposition );
|
||||
|
||||
if (io->u.Status == STATUS_BAD_DEVICE_TYPE)
|
||||
{
|
||||
SERVER_START_REQ( open_file_object )
|
||||
{
|
||||
req->access = access;
|
||||
req->attributes = attr->Attributes;
|
||||
req->rootdir = wine_server_obj_handle( attr->RootDirectory );
|
||||
req->sharing = sharing;
|
||||
req->options = options;
|
||||
wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
|
||||
io->u.Status = wine_server_call( req );
|
||||
*handle = wine_server_ptr_handle( reply->handle );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (io->u.Status == STATUS_SUCCESS) io->Information = FILE_OPENED;
|
||||
return io->u.Status;
|
||||
}
|
||||
|
||||
if (io->u.Status == STATUS_NO_SUCH_FILE && disposition != FILE_OPEN && disposition != FILE_OVERWRITE)
|
||||
{
|
||||
created = TRUE;
|
||||
io->u.Status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (io->u.Status == STATUS_SUCCESS)
|
||||
{
|
||||
static UNICODE_STRING empty_string;
|
||||
OBJECT_ATTRIBUTES unix_attr = *attr;
|
||||
data_size_t len;
|
||||
struct object_attributes *objattr;
|
||||
|
||||
unix_attr.ObjectName = &empty_string; /* we send the unix name instead */
|
||||
if ((io->u.Status = alloc_object_attributes( &unix_attr, &objattr, &len )))
|
||||
{
|
||||
RtlFreeAnsiString( &unix_name );
|
||||
return io->u.Status;
|
||||
}
|
||||
SERVER_START_REQ( create_file )
|
||||
{
|
||||
req->access = access;
|
||||
req->sharing = sharing;
|
||||
req->create = disposition;
|
||||
req->options = options;
|
||||
req->attrs = attributes;
|
||||
wine_server_add_data( req, objattr, len );
|
||||
wine_server_add_data( req, unix_name.Buffer, unix_name.Length );
|
||||
io->u.Status = wine_server_call( req );
|
||||
*handle = wine_server_ptr_handle( reply->handle );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
RtlFreeHeap( GetProcessHeap(), 0, objattr );
|
||||
RtlFreeAnsiString( &unix_name );
|
||||
}
|
||||
else WARN( "%s not found (%x)\n", debugstr_us(attr->ObjectName), io->u.Status );
|
||||
|
||||
if (io->u.Status == STATUS_SUCCESS)
|
||||
{
|
||||
if (created) io->Information = FILE_CREATED;
|
||||
else switch(disposition)
|
||||
{
|
||||
case FILE_SUPERSEDE:
|
||||
io->Information = FILE_SUPERSEDED;
|
||||
break;
|
||||
case FILE_CREATE:
|
||||
io->Information = FILE_CREATED;
|
||||
break;
|
||||
case FILE_OPEN:
|
||||
case FILE_OPEN_IF:
|
||||
io->Information = FILE_OPENED;
|
||||
break;
|
||||
case FILE_OVERWRITE:
|
||||
case FILE_OVERWRITE_IF:
|
||||
io->Information = FILE_OVERWRITTEN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (io->u.Status == STATUS_TOO_MANY_OPENED_FILES)
|
||||
{
|
||||
static int once;
|
||||
if (!once++) ERR_(winediag)( "Too many open files, ulimit -n probably needs to be increased\n" );
|
||||
}
|
||||
|
||||
return io->u.Status;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* NtOpenFile (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtOpenFile( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr,
|
||||
IO_STATUS_BLOCK *io, ULONG sharing, ULONG options )
|
||||
{
|
||||
return NtCreateFile( handle, access, attr, io, NULL, 0, sharing, FILE_OPEN, options, NULL, 0 );
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* NtCreateMailslotFile (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtCreateMailslotFile( HANDLE *handle, ULONG access, OBJECT_ATTRIBUTES *attr,
|
||||
IO_STATUS_BLOCK *io, ULONG options, ULONG quota, ULONG msg_size,
|
||||
LARGE_INTEGER *timeout )
|
||||
{
|
||||
NTSTATUS status;
|
||||
data_size_t len;
|
||||
struct object_attributes *objattr;
|
||||
|
||||
TRACE( "%p %08x %p %p %08x %08x %08x %p\n",
|
||||
handle, access, attr, io, options, quota, msg_size, timeout );
|
||||
|
||||
if (!handle) return STATUS_ACCESS_VIOLATION;
|
||||
if (!attr) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
if ((status = alloc_object_attributes( attr, &objattr, &len ))) return status;
|
||||
|
||||
SERVER_START_REQ( create_mailslot )
|
||||
{
|
||||
req->access = access;
|
||||
req->max_msgsize = msg_size;
|
||||
req->read_timeout = timeout ? timeout->QuadPart : -1;
|
||||
wine_server_add_data( req, objattr, len );
|
||||
if (!(status = wine_server_call( req ))) *handle = wine_server_ptr_handle( reply->handle );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
RtlFreeHeap( GetProcessHeap(), 0, objattr );
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* NtCreateNamedPipeFile (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtCreateNamedPipeFile( HANDLE *handle, ULONG access, OBJECT_ATTRIBUTES *attr,
|
||||
IO_STATUS_BLOCK *io, ULONG sharing, ULONG dispo, ULONG options,
|
||||
ULONG pipe_type, ULONG read_mode, ULONG completion_mode,
|
||||
ULONG max_inst, ULONG inbound_quota, ULONG outbound_quota,
|
||||
LARGE_INTEGER *timeout )
|
||||
{
|
||||
NTSTATUS status;
|
||||
data_size_t len;
|
||||
struct object_attributes *objattr;
|
||||
|
||||
if (!attr) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
TRACE( "(%p %x %s %p %x %d %x %d %d %d %d %d %d %p)\n",
|
||||
handle, access, debugstr_us(attr->ObjectName), io, sharing, dispo,
|
||||
options, pipe_type, read_mode, completion_mode, max_inst, inbound_quota,
|
||||
outbound_quota, timeout );
|
||||
|
||||
/* assume we only get relative timeout */
|
||||
if (timeout->QuadPart > 0) FIXME( "Wrong time %s\n", wine_dbgstr_longlong(timeout->QuadPart) );
|
||||
|
||||
if ((status = alloc_object_attributes( attr, &objattr, &len ))) return status;
|
||||
|
||||
SERVER_START_REQ( create_named_pipe )
|
||||
{
|
||||
req->access = access;
|
||||
req->options = options;
|
||||
req->sharing = sharing;
|
||||
req->flags =
|
||||
(pipe_type ? NAMED_PIPE_MESSAGE_STREAM_WRITE : 0) |
|
||||
(read_mode ? NAMED_PIPE_MESSAGE_STREAM_READ : 0) |
|
||||
(completion_mode ? NAMED_PIPE_NONBLOCKING_MODE : 0);
|
||||
req->maxinstances = max_inst;
|
||||
req->outsize = outbound_quota;
|
||||
req->insize = inbound_quota;
|
||||
req->timeout = timeout->QuadPart;
|
||||
wine_server_add_data( req, objattr, len );
|
||||
if (!(status = wine_server_call( req ))) *handle = wine_server_ptr_handle( reply->handle );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
RtlFreeHeap( GetProcessHeap(), 0, objattr );
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* NtDeleteFile (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtDeleteFile( OBJECT_ATTRIBUTES *attr )
|
||||
{
|
||||
HANDLE handle;
|
||||
NTSTATUS status;
|
||||
IO_STATUS_BLOCK io;
|
||||
|
||||
status = NtCreateFile( &handle, GENERIC_READ | GENERIC_WRITE | DELETE, attr, &io, NULL, 0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN,
|
||||
FILE_DELETE_ON_CLOSE, NULL, 0 );
|
||||
if (status == STATUS_SUCCESS) NtClose( handle );
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* NtQueryFullAttributesFile (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr,
|
||||
FILE_NETWORK_OPEN_INFORMATION *info )
|
||||
{
|
||||
ANSI_STRING unix_name;
|
||||
NTSTATUS status;
|
||||
|
||||
if (!(status = nt_to_unix_file_name_attr( attr, &unix_name, FILE_OPEN )))
|
||||
{
|
||||
ULONG attributes;
|
||||
struct stat st;
|
||||
|
||||
if (get_file_info( unix_name.Buffer, &st, &attributes ) == -1)
|
||||
status = errno_to_status( errno );
|
||||
else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
|
||||
status = STATUS_INVALID_INFO_CLASS;
|
||||
else
|
||||
{
|
||||
FILE_BASIC_INFORMATION basic;
|
||||
FILE_STANDARD_INFORMATION std;
|
||||
|
||||
fill_file_info( &st, attributes, &basic, FileBasicInformation );
|
||||
fill_file_info( &st, attributes, &std, FileStandardInformation );
|
||||
|
||||
info->CreationTime = basic.CreationTime;
|
||||
info->LastAccessTime = basic.LastAccessTime;
|
||||
info->LastWriteTime = basic.LastWriteTime;
|
||||
info->ChangeTime = basic.ChangeTime;
|
||||
info->AllocationSize = std.AllocationSize;
|
||||
info->EndOfFile = std.EndOfFile;
|
||||
info->FileAttributes = basic.FileAttributes;
|
||||
if (is_hidden_file( attr->ObjectName )) info->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
|
||||
}
|
||||
RtlFreeAnsiString( &unix_name );
|
||||
}
|
||||
else WARN( "%s not found (%x)\n", debugstr_us(attr->ObjectName), status );
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* NtQueryAttributesFile (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtQueryAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_BASIC_INFORMATION *info )
|
||||
{
|
||||
ANSI_STRING unix_name;
|
||||
NTSTATUS status;
|
||||
|
||||
if (!(status = nt_to_unix_file_name_attr( attr, &unix_name, FILE_OPEN )))
|
||||
{
|
||||
ULONG attributes;
|
||||
struct stat st;
|
||||
|
||||
if (get_file_info( unix_name.Buffer, &st, &attributes ) == -1)
|
||||
status = errno_to_status( errno );
|
||||
else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
|
||||
status = STATUS_INVALID_INFO_CLASS;
|
||||
else
|
||||
{
|
||||
status = fill_file_info( &st, attributes, info, FileBasicInformation );
|
||||
if (is_hidden_file( attr->ObjectName )) info->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
|
||||
}
|
||||
RtlFreeAnsiString( &unix_name );
|
||||
}
|
||||
else WARN( "%s not found (%x)\n", debugstr_us(attr->ObjectName), status );
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -825,14 +825,18 @@ static struct unix_funcs unix_funcs =
|
|||
NtClose,
|
||||
NtContinue,
|
||||
NtCreateEvent,
|
||||
NtCreateFile,
|
||||
NtCreateKeyedEvent,
|
||||
NtCreateMailslotFile,
|
||||
NtCreateMutant,
|
||||
NtCreateNamedPipeFile,
|
||||
NtCreateSection,
|
||||
NtCreateSemaphore,
|
||||
NtCreateThreadEx,
|
||||
NtCreateTimer,
|
||||
NtCurrentTeb,
|
||||
NtDelayExecution,
|
||||
NtDeleteFile,
|
||||
NtDuplicateObject,
|
||||
NtFlushVirtualMemory,
|
||||
NtFreeVirtualMemory,
|
||||
|
@ -841,6 +845,7 @@ static struct unix_funcs unix_funcs =
|
|||
NtLockVirtualMemory,
|
||||
NtMapViewOfSection,
|
||||
NtOpenEvent,
|
||||
NtOpenFile,
|
||||
NtOpenKeyedEvent,
|
||||
NtOpenMutant,
|
||||
NtOpenSection,
|
||||
|
@ -849,8 +854,10 @@ static struct unix_funcs unix_funcs =
|
|||
NtOpenTimer,
|
||||
NtProtectVirtualMemory,
|
||||
NtPulseEvent,
|
||||
NtQueryAttributesFile,
|
||||
NtQueryDirectoryFile,
|
||||
NtQueryEvent,
|
||||
NtQueryFullAttributesFile,
|
||||
NtQueryMutant,
|
||||
NtQueryPerformanceCounter,
|
||||
NtQuerySection,
|
||||
|
|
|
@ -28,7 +28,7 @@ struct ldt_copy;
|
|||
struct msghdr;
|
||||
|
||||
/* increment this when you change the function table */
|
||||
#define NTDLL_UNIXLIB_VERSION 42
|
||||
#define NTDLL_UNIXLIB_VERSION 43
|
||||
|
||||
struct unix_funcs
|
||||
{
|
||||
|
@ -44,10 +44,23 @@ struct unix_funcs
|
|||
NTSTATUS (WINAPI *NtContinue)( CONTEXT *context, BOOLEAN alertable );
|
||||
NTSTATUS (WINAPI *NtCreateEvent)( HANDLE *handle, ACCESS_MASK access,
|
||||
const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN state );
|
||||
NTSTATUS (WINAPI *NtCreateFile)( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr,
|
||||
IO_STATUS_BLOCK *io, LARGE_INTEGER *alloc_size,
|
||||
ULONG attributes, ULONG sharing, ULONG disposition,
|
||||
ULONG options, void *ea_buffer, ULONG ea_length );
|
||||
NTSTATUS (WINAPI *NtCreateKeyedEvent)( HANDLE *handle, ACCESS_MASK access,
|
||||
const OBJECT_ATTRIBUTES *attr, ULONG flags );
|
||||
NTSTATUS (WINAPI *NtCreateMailslotFile)( HANDLE *handle, ULONG access, OBJECT_ATTRIBUTES *attr,
|
||||
IO_STATUS_BLOCK *io, ULONG options, ULONG quota,
|
||||
ULONG msg_size, LARGE_INTEGER *timeout );
|
||||
NTSTATUS (WINAPI *NtCreateMutant)( HANDLE *handle, ACCESS_MASK access,
|
||||
const OBJECT_ATTRIBUTES *attr, BOOLEAN owned );
|
||||
NTSTATUS (WINAPI *NtCreateNamedPipeFile)( HANDLE *handle, ULONG access, OBJECT_ATTRIBUTES *attr,
|
||||
IO_STATUS_BLOCK *io, ULONG sharing, ULONG dispo,
|
||||
ULONG options, ULONG pipe_type, ULONG read_mode,
|
||||
ULONG completion_mode, ULONG max_inst,
|
||||
ULONG inbound_quota, ULONG outbound_quota,
|
||||
LARGE_INTEGER *timeout );
|
||||
NTSTATUS (WINAPI *NtCreateSection)( HANDLE *handle, ACCESS_MASK access,
|
||||
const OBJECT_ATTRIBUTES *attr, const LARGE_INTEGER *size,
|
||||
ULONG protect, ULONG sec_flags, HANDLE file );
|
||||
|
@ -61,6 +74,7 @@ struct unix_funcs
|
|||
const OBJECT_ATTRIBUTES *attr, TIMER_TYPE type );
|
||||
TEB * (WINAPI *NtCurrentTeb)(void);
|
||||
NTSTATUS (WINAPI *NtDelayExecution)( BOOLEAN alertable, const LARGE_INTEGER *timeout );
|
||||
NTSTATUS (WINAPI *NtDeleteFile)( OBJECT_ATTRIBUTES *attr );
|
||||
NTSTATUS (WINAPI *NtDuplicateObject)( HANDLE source_process, HANDLE source,
|
||||
HANDLE dest_process, HANDLE *dest,
|
||||
ACCESS_MASK access, ULONG attributes, ULONG options );
|
||||
|
@ -78,6 +92,8 @@ struct unix_funcs
|
|||
SECTION_INHERIT inherit, ULONG alloc_type, ULONG protect );
|
||||
NTSTATUS (WINAPI *NtOpenEvent)( HANDLE *handle, ACCESS_MASK access,
|
||||
const OBJECT_ATTRIBUTES *attr );
|
||||
NTSTATUS (WINAPI *NtOpenFile)( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr,
|
||||
IO_STATUS_BLOCK *io, ULONG sharing, ULONG options );
|
||||
NTSTATUS (WINAPI *NtOpenKeyedEvent)( HANDLE *handle, ACCESS_MASK access,
|
||||
const OBJECT_ATTRIBUTES *attr );
|
||||
NTSTATUS (WINAPI *NtOpenMutant)( HANDLE *handle, ACCESS_MASK access,
|
||||
|
@ -92,6 +108,8 @@ struct unix_funcs
|
|||
NTSTATUS (WINAPI *NtProtectVirtualMemory)( HANDLE process, PVOID *addr_ptr, SIZE_T *size_ptr,
|
||||
ULONG new_prot, ULONG *old_prot );
|
||||
NTSTATUS (WINAPI *NtPulseEvent)( HANDLE handle, LONG *prev_state );
|
||||
NTSTATUS (WINAPI *NtQueryAttributesFile)( const OBJECT_ATTRIBUTES *attr,
|
||||
FILE_BASIC_INFORMATION *info );
|
||||
NTSTATUS (WINAPI *NtQueryDirectoryFile)( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc_routine,
|
||||
void *apc_context, IO_STATUS_BLOCK *io, void *buffer,
|
||||
ULONG length, FILE_INFORMATION_CLASS info_class,
|
||||
|
@ -99,6 +117,8 @@ struct unix_funcs
|
|||
BOOLEAN restart_scan );
|
||||
NTSTATUS (WINAPI *NtQueryEvent)( HANDLE handle, EVENT_INFORMATION_CLASS class,
|
||||
void *info, ULONG len, ULONG *ret_len );
|
||||
NTSTATUS (WINAPI *NtQueryFullAttributesFile)( const OBJECT_ATTRIBUTES *attr,
|
||||
FILE_NETWORK_OPEN_INFORMATION *info );
|
||||
NTSTATUS (WINAPI *NtQueryMutant)( HANDLE handle, MUTANT_INFORMATION_CLASS class,
|
||||
void *info, ULONG len, ULONG *ret_len );
|
||||
NTSTATUS (WINAPI *NtQueryPerformanceCounter)( LARGE_INTEGER *counter, LARGE_INTEGER *frequency );
|
||||
|
|
Loading…
Reference in New Issue