diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c index e353c9223fb..6bb5a993ebf 100644 --- a/dlls/ntdll/directory.c +++ b/dlls/ntdll/directory.c @@ -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.@] diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index e2026ad336b..b3e881ac3c9 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -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 ); } diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index d03baf70a79..d4b8fd11068 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -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; diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index d80f419220d..13096e085e8 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -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; +} diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 3be60368918..b09049b855b 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -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, diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h index 99fdffa2cf3..958fab4c059 100644 --- a/dlls/ntdll/unixlib.h +++ b/dlls/ntdll/unixlib.h @@ -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 );