Implemented NtCreatelFile using the new symlink scheme.
Use NtCreateFile in the loader, and get rid of the CreateFileW upcall hack.
This commit is contained in:
parent
2392a36370
commit
e792fb74ba
|
@ -53,6 +53,7 @@
|
||||||
#include "ntdll_misc.h"
|
#include "ntdll_misc.h"
|
||||||
#include "wine/unicode.h"
|
#include "wine/unicode.h"
|
||||||
#include "wine/server.h"
|
#include "wine/server.h"
|
||||||
|
#include "wine/library.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(file);
|
WINE_DEFAULT_DEBUG_CHANNEL(file);
|
||||||
|
@ -71,11 +72,16 @@ typedef struct
|
||||||
|
|
||||||
#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, KERNEL_DIRENT [2] )
|
#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, KERNEL_DIRENT [2] )
|
||||||
|
|
||||||
|
#ifndef O_DIRECTORY
|
||||||
|
# define O_DIRECTORY 0200000 /* must be directory */
|
||||||
|
#endif
|
||||||
|
|
||||||
#else /* linux */
|
#else /* linux */
|
||||||
#undef VFAT_IOCTL_READDIR_BOTH /* just in case... */
|
#undef VFAT_IOCTL_READDIR_BOTH /* just in case... */
|
||||||
#endif /* linux */
|
#endif /* linux */
|
||||||
|
|
||||||
#define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
|
#define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
|
||||||
|
#define IS_SEPARATOR(ch) ((ch) == '\\' || (ch) == '/')
|
||||||
|
|
||||||
#define INVALID_DOS_CHARS '*','?','<','>','|','"','+','=',',',';','[',']',' ','\345'
|
#define INVALID_DOS_CHARS '*','?','<','>','|','"','+','=',',',';','[',']',' ','\345'
|
||||||
|
|
||||||
|
@ -572,3 +578,297 @@ NTSTATUS WINAPI NtQueryDirectoryFile( HANDLE handle, HANDLE event,
|
||||||
TRACE( "=> %lx (%ld)\n", io->u.Status, io->Information );
|
TRACE( "=> %lx (%ld)\n", io->u.Status, io->Information );
|
||||||
return io->u.Status;
|
return io->u.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* find_file_in_dir
|
||||||
|
*
|
||||||
|
* Find a file in a directory the hard way, by doing a case-insensitive search.
|
||||||
|
* The file found is appended to unix_name at pos.
|
||||||
|
* There must be at least MAX_DIR_ENTRY_LEN+2 chars available at pos.
|
||||||
|
*/
|
||||||
|
static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, int length,
|
||||||
|
int is_last, int check_last, int check_case )
|
||||||
|
{
|
||||||
|
WCHAR buffer[MAX_DIR_ENTRY_LEN];
|
||||||
|
UNICODE_STRING str;
|
||||||
|
BOOLEAN spaces;
|
||||||
|
DIR *dir;
|
||||||
|
struct dirent *de;
|
||||||
|
struct stat st;
|
||||||
|
int ret, used_default, is_name_8_dot_3;
|
||||||
|
|
||||||
|
/* try a shortcut for this directory */
|
||||||
|
|
||||||
|
unix_name[pos++] = '/';
|
||||||
|
ret = ntdll_wcstoumbs( 0, name, length, unix_name + pos, MAX_DIR_ENTRY_LEN,
|
||||||
|
NULL, &used_default );
|
||||||
|
/* if we used the default char, the Unix name won't round trip properly back to Unicode */
|
||||||
|
/* so it cannot match the file we are looking for */
|
||||||
|
if (ret >= 0 && !used_default)
|
||||||
|
{
|
||||||
|
unix_name[pos + ret] = 0;
|
||||||
|
if (!stat( unix_name, &st )) return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
if (check_case) goto not_found; /* we want an exact match */
|
||||||
|
|
||||||
|
if (pos > 1) unix_name[pos - 1] = 0;
|
||||||
|
else unix_name[1] = 0; /* keep the initial slash */
|
||||||
|
|
||||||
|
/* check if it fits in 8.3 so that we don't look for short names if we won't need them */
|
||||||
|
|
||||||
|
str.Buffer = (WCHAR *)name;
|
||||||
|
str.Length = length * sizeof(WCHAR);
|
||||||
|
str.MaximumLength = str.Length;
|
||||||
|
is_name_8_dot_3 = RtlIsNameLegalDOS8Dot3( &str, NULL, &spaces ) && !spaces;
|
||||||
|
|
||||||
|
/* now look for it through the directory */
|
||||||
|
|
||||||
|
#ifdef VFAT_IOCTL_READDIR_BOTH
|
||||||
|
if (is_name_8_dot_3)
|
||||||
|
{
|
||||||
|
int fd = open( unix_name, O_RDONLY | O_DIRECTORY );
|
||||||
|
if (fd != -1)
|
||||||
|
{
|
||||||
|
KERNEL_DIRENT de[2];
|
||||||
|
|
||||||
|
if (ioctl( fd, VFAT_IOCTL_READDIR_BOTH, (long)de ) != -1)
|
||||||
|
{
|
||||||
|
unix_name[pos - 1] = '/';
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (!de[0].d_reclen) break;
|
||||||
|
|
||||||
|
if (de[1].d_name[0])
|
||||||
|
{
|
||||||
|
ret = ntdll_umbstowcs( 0, de[1].d_name, strlen(de[1].d_name),
|
||||||
|
buffer, MAX_DIR_ENTRY_LEN );
|
||||||
|
if (ret == length && !memicmpW( buffer, name, length))
|
||||||
|
{
|
||||||
|
strcpy( unix_name + pos, de[1].d_name );
|
||||||
|
close( fd );
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = ntdll_umbstowcs( 0, de[0].d_name, strlen(de[0].d_name),
|
||||||
|
buffer, MAX_DIR_ENTRY_LEN );
|
||||||
|
if (ret == length && !memicmpW( buffer, name, length))
|
||||||
|
{
|
||||||
|
strcpy( unix_name + pos,
|
||||||
|
de[1].d_name[0] ? de[1].d_name : de[0].d_name );
|
||||||
|
close( fd );
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
if (ioctl( fd, VFAT_IOCTL_READDIR_BOTH, (long)de ) == -1)
|
||||||
|
{
|
||||||
|
close( fd );
|
||||||
|
goto not_found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close( fd );
|
||||||
|
}
|
||||||
|
/* fall through to normal handling */
|
||||||
|
}
|
||||||
|
#endif /* VFAT_IOCTL_READDIR_BOTH */
|
||||||
|
|
||||||
|
if (!(dir = opendir( unix_name ))) return FILE_GetNtStatus();
|
||||||
|
unix_name[pos - 1] = '/';
|
||||||
|
str.Buffer = buffer;
|
||||||
|
str.MaximumLength = sizeof(buffer);
|
||||||
|
while ((de = readdir( dir )))
|
||||||
|
{
|
||||||
|
ret = ntdll_umbstowcs( 0, de->d_name, strlen(de->d_name), buffer, MAX_DIR_ENTRY_LEN );
|
||||||
|
if (ret == length && !memicmpW( buffer, name, length ))
|
||||||
|
{
|
||||||
|
strcpy( unix_name + pos, de->d_name );
|
||||||
|
closedir( dir );
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_name_8_dot_3) continue;
|
||||||
|
|
||||||
|
str.Length = ret * sizeof(WCHAR);
|
||||||
|
if (!RtlIsNameLegalDOS8Dot3( &str, NULL, &spaces ) || spaces)
|
||||||
|
{
|
||||||
|
WCHAR short_nameW[12];
|
||||||
|
ret = hash_short_file_name( &str, short_nameW );
|
||||||
|
if (ret == length && !memicmpW( short_nameW, name, length ))
|
||||||
|
{
|
||||||
|
strcpy( unix_name + pos, de->d_name );
|
||||||
|
closedir( dir );
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir( dir );
|
||||||
|
goto not_found; /* avoid warning */
|
||||||
|
|
||||||
|
not_found:
|
||||||
|
if (is_last && !check_last) /* return the name anyway */
|
||||||
|
{
|
||||||
|
int used_default;
|
||||||
|
ret = ntdll_wcstoumbs( 0, name, length, unix_name + pos,
|
||||||
|
MAX_DIR_ENTRY_LEN, NULL, &used_default );
|
||||||
|
if (ret > 0 && !used_default)
|
||||||
|
{
|
||||||
|
unix_name[pos + ret] = 0;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unix_name[pos - 1] = 0;
|
||||||
|
return is_last ? STATUS_NO_SUCH_FILE : STATUS_OBJECT_PATH_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* return the length of the DOS namespace prefix if any */
|
||||||
|
static inline int get_dos_prefix_len( const UNICODE_STRING *name )
|
||||||
|
{
|
||||||
|
static const WCHAR nt_prefixW[] = {'\\','?','?','\\'};
|
||||||
|
static const WCHAR dosdev_prefixW[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\'};
|
||||||
|
|
||||||
|
if (name->Length > sizeof(nt_prefixW) &&
|
||||||
|
!memcmp( name->Buffer, nt_prefixW, sizeof(nt_prefixW) ))
|
||||||
|
return sizeof(nt_prefixW) / sizeof(WCHAR);
|
||||||
|
|
||||||
|
if (name->Length > sizeof(dosdev_prefixW) &&
|
||||||
|
!memicmpW( name->Buffer, dosdev_prefixW, sizeof(dosdev_prefixW)/sizeof(WCHAR) ))
|
||||||
|
return sizeof(dosdev_prefixW) / sizeof(WCHAR);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* DIR_nt_to_unix
|
||||||
|
*
|
||||||
|
* Convert a file name from NT namespace to Unix namespace.
|
||||||
|
*/
|
||||||
|
NTSTATUS DIR_nt_to_unix( const UNICODE_STRING *nameW, ANSI_STRING *unix_name_ret,
|
||||||
|
int check_last, int check_case )
|
||||||
|
{
|
||||||
|
NTSTATUS status = STATUS_NO_SUCH_FILE;
|
||||||
|
const char *config_dir = wine_get_config_dir();
|
||||||
|
const WCHAR *end, *name;
|
||||||
|
struct stat st;
|
||||||
|
char *unix_name;
|
||||||
|
int pos, ret, name_len, unix_len, used_default;
|
||||||
|
|
||||||
|
name = nameW->Buffer;
|
||||||
|
name_len = nameW->Length / sizeof(WCHAR);
|
||||||
|
|
||||||
|
if ((pos = get_dos_prefix_len( nameW )))
|
||||||
|
{
|
||||||
|
name += pos;
|
||||||
|
name_len -= pos;
|
||||||
|
if (name_len < 3 || !isalphaW(name[0]) || name[1] != ':' || !IS_SEPARATOR(name[2]))
|
||||||
|
return STATUS_NO_SUCH_FILE;
|
||||||
|
name += 2; /* skip drive letter */
|
||||||
|
name_len -= 2;
|
||||||
|
unix_len = ntdll_wcstoumbs( 0, name, name_len, NULL, 0, NULL, NULL );
|
||||||
|
unix_len += MAX_DIR_ENTRY_LEN + 3;
|
||||||
|
unix_len += strlen(config_dir) + sizeof("/dosdevices/a:");
|
||||||
|
if (!(unix_name = RtlAllocateHeap( GetProcessHeap(), 0, unix_len )))
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
strcpy( unix_name, config_dir );
|
||||||
|
strcat( unix_name, "/dosdevices/a:" );
|
||||||
|
pos = strlen(unix_name);
|
||||||
|
unix_name[pos - 2] = tolowerW( name[-2] );
|
||||||
|
}
|
||||||
|
else /* no DOS prefix, assume NT native name, map directly to Unix */
|
||||||
|
{
|
||||||
|
if (!name_len || !IS_SEPARATOR(name[0])) return STATUS_NO_SUCH_FILE;
|
||||||
|
unix_len = ntdll_wcstoumbs( 0, name, name_len, NULL, 0, NULL, NULL );
|
||||||
|
unix_len += MAX_DIR_ENTRY_LEN + 3;
|
||||||
|
if (!(unix_name = RtlAllocateHeap( GetProcessHeap(), 0, unix_len )))
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* try a shortcut first */
|
||||||
|
|
||||||
|
ret = ntdll_wcstoumbs( 0, name, name_len, unix_name + pos, unix_len - pos - 1,
|
||||||
|
NULL, &used_default );
|
||||||
|
if (ret > 0 && !used_default) /* if we used the default char the name didn't convert properly */
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
unix_name[pos + ret] = 0;
|
||||||
|
for (p = unix_name + pos ; *p; p++) if (*p == '\\') *p = '/';
|
||||||
|
if (!stat( unix_name, &st )) goto done;
|
||||||
|
}
|
||||||
|
if (check_case && check_last)
|
||||||
|
{
|
||||||
|
RtlFreeHeap( GetProcessHeap(), 0, unix_name );
|
||||||
|
return STATUS_NO_SUCH_FILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now do it component by component */
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
while (name_len && IS_SEPARATOR(*name))
|
||||||
|
{
|
||||||
|
name++;
|
||||||
|
name_len--;
|
||||||
|
}
|
||||||
|
if (!name_len) break;
|
||||||
|
|
||||||
|
end = name;
|
||||||
|
while (end < name + name_len && !IS_SEPARATOR(*end)) end++;
|
||||||
|
|
||||||
|
/* grow the buffer if needed */
|
||||||
|
|
||||||
|
if (unix_len - pos < MAX_DIR_ENTRY_LEN + 2)
|
||||||
|
{
|
||||||
|
char *new_name;
|
||||||
|
unix_len += 2 * MAX_DIR_ENTRY_LEN;
|
||||||
|
if (!(new_name = RtlReAllocateHeap( GetProcessHeap(), 0, unix_name, unix_len )))
|
||||||
|
{
|
||||||
|
RtlFreeHeap( GetProcessHeap(), 0, unix_name );
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
unix_name = new_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = find_file_in_dir( unix_name, pos, name, end - name,
|
||||||
|
(end - name == name_len), check_last, check_case );
|
||||||
|
if (status != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
/* couldn't find it at all, fail */
|
||||||
|
WARN( "%s not found in %s\n", debugstr_w(name), unix_name );
|
||||||
|
RtlFreeHeap( GetProcessHeap(), 0, unix_name );
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += strlen( unix_name + pos );
|
||||||
|
name_len -= end - name;
|
||||||
|
name = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
WARN( "%s -> %s required a case-insensitive search\n",
|
||||||
|
debugstr_us(nameW), debugstr_a(unix_name) );
|
||||||
|
|
||||||
|
done:
|
||||||
|
TRACE( "%s -> %s\n", debugstr_us(nameW), debugstr_a(unix_name) );
|
||||||
|
unix_name_ret->Buffer = unix_name;
|
||||||
|
unix_name_ret->Length = strlen(unix_name);
|
||||||
|
unix_name_ret->MaximumLength = unix_len;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* RtlDoesFileExists_U (NTDLL.@)
|
||||||
|
*/
|
||||||
|
BOOLEAN WINAPI RtlDoesFileExists_U(LPCWSTR file_name)
|
||||||
|
{
|
||||||
|
UNICODE_STRING nt_name;
|
||||||
|
ANSI_STRING unix_name;
|
||||||
|
BOOLEAN ret;
|
||||||
|
|
||||||
|
if (!RtlDosPathNameToNtPathName_U( file_name, &nt_name, NULL, NULL )) return FALSE;
|
||||||
|
ret = (DIR_nt_to_unix( &nt_name, &unix_name, TRUE, FALSE ) == STATUS_SUCCESS);
|
||||||
|
if (ret) RtlFreeAnsiString( &unix_name );
|
||||||
|
RtlFreeUnicodeString( &nt_name );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -71,52 +71,23 @@ WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
|
||||||
* Open a file.
|
* Open a file.
|
||||||
*
|
*
|
||||||
* PARAMS
|
* PARAMS
|
||||||
* FileHandle [O] Variable that receives the file handle on return
|
* handle [O] Variable that receives the file handle on return
|
||||||
* DesiredAccess [I] Access desired by the caller to the file
|
* access [I] Access desired by the caller to the file
|
||||||
* ObjectAttributes [I] Structue describing the file to be opened
|
* attr [I] Structue describing the file to be opened
|
||||||
* IoStatusBlock [O] Receives details about the result of the operation
|
* io [O] Receives details about the result of the operation
|
||||||
* ShareAccess [I] Type of shared access the caller requires
|
* sharing [I] Type of shared access the caller requires
|
||||||
* OpenOptions [I] Options for the file open
|
* options [I] Options for the file open
|
||||||
*
|
*
|
||||||
* RETURNS
|
* RETURNS
|
||||||
* Success: 0. FileHandle and IoStatusBlock are updated.
|
* Success: 0. FileHandle and IoStatusBlock are updated.
|
||||||
* Failure: An NTSTATUS error code describing the error.
|
* Failure: An NTSTATUS error code describing the error.
|
||||||
*/
|
*/
|
||||||
NTSTATUS WINAPI NtOpenFile(
|
NTSTATUS WINAPI NtOpenFile( PHANDLE handle, ACCESS_MASK access,
|
||||||
OUT PHANDLE FileHandle,
|
POBJECT_ATTRIBUTES attr, PIO_STATUS_BLOCK io,
|
||||||
ACCESS_MASK DesiredAccess,
|
ULONG sharing, ULONG options )
|
||||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
|
||||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
|
||||||
ULONG ShareAccess,
|
|
||||||
ULONG OpenOptions)
|
|
||||||
{
|
{
|
||||||
LPWSTR filename;
|
return NtCreateFile( handle, access, attr, io, NULL, 0,
|
||||||
static const WCHAR szDosDevices[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0};
|
sharing, FILE_OPEN, options, NULL, 0 );
|
||||||
|
|
||||||
FIXME("(%p,0x%08lx,%p,%p,0x%08lx,0x%08lx) partial stub\n",
|
|
||||||
FileHandle, DesiredAccess, ObjectAttributes,
|
|
||||||
IoStatusBlock, ShareAccess, OpenOptions);
|
|
||||||
|
|
||||||
dump_ObjectAttributes (ObjectAttributes);
|
|
||||||
|
|
||||||
if(ObjectAttributes->RootDirectory)
|
|
||||||
{
|
|
||||||
FIXME("Object root directory unknown %p\n",
|
|
||||||
ObjectAttributes->RootDirectory);
|
|
||||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
filename = ObjectAttributes->ObjectName->Buffer;
|
|
||||||
|
|
||||||
/* FIXME: DOSFS stuff should call here, not vice-versa */
|
|
||||||
if(strncmpW(filename, szDosDevices, strlenW(szDosDevices)))
|
|
||||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
|
||||||
|
|
||||||
/* FIXME: this calls SetLastError() -> bad */
|
|
||||||
*FileHandle = pCreateFileW( &filename[strlenW(szDosDevices)], DesiredAccess, ShareAccess,
|
|
||||||
NULL, OPEN_EXISTING, 0, 0 );
|
|
||||||
if (*FileHandle == INVALID_HANDLE_VALUE) return STATUS_OBJECT_NAME_NOT_FOUND;
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
|
@ -127,41 +98,63 @@ NTSTATUS WINAPI NtOpenFile(
|
||||||
* directory or volume.
|
* directory or volume.
|
||||||
*
|
*
|
||||||
* PARAMS
|
* PARAMS
|
||||||
* FileHandle [O] Points to a variable which receives the file handle on return
|
* handle [O] Points to a variable which receives the file handle on return
|
||||||
* DesiredAccess [I] Desired access to the file
|
* access [I] Desired access to the file
|
||||||
* ObjectAttributes [I] Structure describing the file
|
* attr [I] Structure describing the file
|
||||||
* IoStatusBlock [O] Receives information about the operation on return
|
* io [O] Receives information about the operation on return
|
||||||
* AllocationSize [I] Initial size of the file in bytes
|
* alloc_size [I] Initial size of the file in bytes
|
||||||
* FileAttributes [I] Attributes to create the file with
|
* attributes [I] Attributes to create the file with
|
||||||
* ShareAccess [I] Type of shared access the caller would like to the file
|
* sharing [I] Type of shared access the caller would like to the file
|
||||||
* CreateDisposition [I] Specifies what to do, depending on whether the file already exists
|
* disposition [I] Specifies what to do, depending on whether the file already exists
|
||||||
* CreateOptions [I] Options for creating a new file
|
* options [I] Options for creating a new file
|
||||||
* EaBuffer [I] Undocumented
|
* ea_buffer [I] Undocumented
|
||||||
* EaLength [I] Undocumented
|
* ea_length [I] Undocumented
|
||||||
*
|
*
|
||||||
* RETURNS
|
* RETURNS
|
||||||
* Success: 0. FileHandle and IoStatusBlock are updated.
|
* Success: 0. handle and io are updated.
|
||||||
* Failure: An NTSTATUS error code describing the error.
|
* Failure: An NTSTATUS error code describing the error.
|
||||||
*/
|
*/
|
||||||
NTSTATUS WINAPI NtCreateFile(
|
NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIBUTES attr,
|
||||||
OUT PHANDLE FileHandle,
|
PIO_STATUS_BLOCK io, PLARGE_INTEGER alloc_size,
|
||||||
ACCESS_MASK DesiredAccess,
|
ULONG attributes, ULONG sharing, ULONG disposition,
|
||||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
ULONG options, PVOID ea_buffer, ULONG ea_length )
|
||||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
|
||||||
PLARGE_INTEGER AllocateSize,
|
|
||||||
ULONG FileAttributes,
|
|
||||||
ULONG ShareAccess,
|
|
||||||
ULONG CreateDisposition,
|
|
||||||
ULONG CreateOptions,
|
|
||||||
PVOID EaBuffer,
|
|
||||||
ULONG EaLength)
|
|
||||||
{
|
{
|
||||||
FIXME("(%p,0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx) stub\n",
|
ANSI_STRING unix_name;
|
||||||
FileHandle,DesiredAccess,ObjectAttributes,
|
|
||||||
IoStatusBlock,AllocateSize,FileAttributes,
|
TRACE("handle=%p access=%08lx name=%s objattr=%08lx root=%p sec=%p io=%p alloc_size=%p\n"
|
||||||
ShareAccess,CreateDisposition,CreateOptions,EaBuffer,EaLength);
|
"attr=%08lx sharing=%08lx disp=%ld options=%08lx ea=%p.0x%08lx\n",
|
||||||
dump_ObjectAttributes (ObjectAttributes);
|
handle, access, debugstr_us(attr->ObjectName), attr->Attributes,
|
||||||
return 0;
|
attr->RootDirectory, attr->SecurityDescriptor, io, alloc_size,
|
||||||
|
attributes, sharing, disposition, options, ea_buffer, ea_length );
|
||||||
|
|
||||||
|
if (attr->RootDirectory)
|
||||||
|
{
|
||||||
|
FIXME( "RootDirectory %p not supported\n", attr->RootDirectory );
|
||||||
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
}
|
||||||
|
if (alloc_size) FIXME( "alloc_size not supported\n" );
|
||||||
|
|
||||||
|
if (!(io->u.Status = DIR_nt_to_unix( attr->ObjectName, &unix_name,
|
||||||
|
(disposition == FILE_OPEN || disposition == FILE_OVERWRITE),
|
||||||
|
!(attr->Attributes & OBJ_CASE_INSENSITIVE) )))
|
||||||
|
{
|
||||||
|
SERVER_START_REQ( create_file )
|
||||||
|
{
|
||||||
|
req->access = access;
|
||||||
|
req->inherit = (attr->Attributes & OBJ_INHERIT) != 0;
|
||||||
|
req->sharing = sharing;
|
||||||
|
req->create = disposition;
|
||||||
|
req->options = options;
|
||||||
|
req->attrs = attributes;
|
||||||
|
wine_server_add_data( req, unix_name.Buffer, unix_name.Length );
|
||||||
|
io->u.Status = wine_server_call( req );
|
||||||
|
*handle = reply->handle;
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
RtlFreeAnsiString( &unix_name );
|
||||||
|
}
|
||||||
|
else WARN("%s not found (%lx)\n", debugstr_us(attr->ObjectName), io->u.Status );
|
||||||
|
return io->u.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -240,7 +233,7 @@ NTSTATUS FILE_GetNtStatus(void)
|
||||||
case EPERM:
|
case EPERM:
|
||||||
case EROFS:
|
case EROFS:
|
||||||
case EACCES: nt = STATUS_ACCESS_DENIED; break;
|
case EACCES: nt = STATUS_ACCESS_DENIED; break;
|
||||||
case ENOENT: nt = STATUS_SHARING_VIOLATION; break;
|
case ENOENT: nt = STATUS_OBJECT_NAME_NOT_FOUND; break;
|
||||||
case EISDIR: nt = STATUS_FILE_IS_A_DIRECTORY; break;
|
case EISDIR: nt = STATUS_FILE_IS_A_DIRECTORY; break;
|
||||||
case EMFILE:
|
case EMFILE:
|
||||||
case ENFILE: nt = STATUS_NO_MORE_FILES; break;
|
case ENFILE: nt = STATUS_NO_MORE_FILES; break;
|
||||||
|
|
|
@ -1333,9 +1333,13 @@ static NTSTATUS load_builtin_dll( LPCWSTR load_path, LPCWSTR path, DWORD flags,
|
||||||
static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,
|
static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,
|
||||||
WCHAR *filename, ULONG *size, WINE_MODREF **pwm, HANDLE *handle )
|
WCHAR *filename, ULONG *size, WINE_MODREF **pwm, HANDLE *handle )
|
||||||
{
|
{
|
||||||
|
OBJECT_ATTRIBUTES attr;
|
||||||
|
IO_STATUS_BLOCK io;
|
||||||
|
UNICODE_STRING nt_name;
|
||||||
WCHAR *file_part, *ext;
|
WCHAR *file_part, *ext;
|
||||||
ULONG len;
|
ULONG len;
|
||||||
|
|
||||||
|
nt_name.Buffer = NULL;
|
||||||
if (RtlDetermineDosPathNameType_U( libname ) == RELATIVE_PATH)
|
if (RtlDetermineDosPathNameType_U( libname ) == RELATIVE_PATH)
|
||||||
{
|
{
|
||||||
/* we need to search for it */
|
/* we need to search for it */
|
||||||
|
@ -1368,7 +1372,17 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,
|
||||||
{
|
{
|
||||||
if ((*pwm = find_basename_module( file_part )) != NULL) return STATUS_SUCCESS;
|
if ((*pwm = find_basename_module( file_part )) != NULL) return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
*handle = pCreateFileW( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
|
if (!RtlDosPathNameToNtPathName_U( filename, &nt_name, NULL, NULL ))
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
|
||||||
|
attr.Length = sizeof(attr);
|
||||||
|
attr.RootDirectory = 0;
|
||||||
|
attr.Attributes = OBJ_CASE_INSENSITIVE;
|
||||||
|
attr.ObjectName = &nt_name;
|
||||||
|
attr.SecurityDescriptor = NULL;
|
||||||
|
attr.SecurityQualityOfService = NULL;
|
||||||
|
if (NtOpenFile( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ, 0 )) *handle = 0;
|
||||||
|
RtlFreeUnicodeString( &nt_name );
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1394,19 +1408,33 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,
|
||||||
|
|
||||||
/* absolute path name, or relative path name but not found above */
|
/* absolute path name, or relative path name but not found above */
|
||||||
|
|
||||||
len = RtlGetFullPathName_U( libname, *size, filename, &file_part );
|
if (!RtlDosPathNameToNtPathName_U( libname, &nt_name, &file_part, NULL ))
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
|
||||||
|
len = nt_name.Length - 4*sizeof(WCHAR); /* for \??\ prefix */
|
||||||
if (len >= *size) goto overflow;
|
if (len >= *size) goto overflow;
|
||||||
|
memcpy( filename, nt_name.Buffer + 4, len + sizeof(WCHAR) );
|
||||||
if (file_part && !strchrW( file_part, '.' ))
|
if (file_part && !strchrW( file_part, '.' ))
|
||||||
{
|
{
|
||||||
len += sizeof(dllW) - sizeof(WCHAR);
|
len += sizeof(dllW) - sizeof(WCHAR);
|
||||||
if (len >= *size) goto overflow;
|
if (len >= *size) goto overflow;
|
||||||
strcatW( file_part, dllW );
|
strcatW( filename, dllW );
|
||||||
}
|
}
|
||||||
if ((*pwm = find_fullname_module( filename )) != NULL) return STATUS_SUCCESS;
|
if (!(*pwm = find_fullname_module( filename )))
|
||||||
*handle = pCreateFileW( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
|
{
|
||||||
|
attr.Length = sizeof(attr);
|
||||||
|
attr.RootDirectory = 0;
|
||||||
|
attr.Attributes = OBJ_CASE_INSENSITIVE;
|
||||||
|
attr.ObjectName = &nt_name;
|
||||||
|
attr.SecurityDescriptor = NULL;
|
||||||
|
attr.SecurityQualityOfService = NULL;
|
||||||
|
if (NtOpenFile( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ, 0 )) *handle = 0;
|
||||||
|
}
|
||||||
|
RtlFreeUnicodeString( &nt_name );
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
overflow:
|
overflow:
|
||||||
|
RtlFreeUnicodeString( &nt_name );
|
||||||
*size = len + sizeof(WCHAR);
|
*size = len + sizeof(WCHAR);
|
||||||
return STATUS_BUFFER_TOO_SMALL;
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
}
|
}
|
||||||
|
@ -1427,7 +1455,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
|
||||||
ULONG size;
|
ULONG size;
|
||||||
const char *filetype = "";
|
const char *filetype = "";
|
||||||
WINE_MODREF *main_exe;
|
WINE_MODREF *main_exe;
|
||||||
HANDLE handle = INVALID_HANDLE_VALUE;
|
HANDLE handle = 0;
|
||||||
NTSTATUS nts;
|
NTSTATUS nts;
|
||||||
|
|
||||||
TRACE( "looking for %s in %s\n", debugstr_w(libname), debugstr_w(load_path) );
|
TRACE( "looking for %s in %s\n", debugstr_w(libname), debugstr_w(load_path) );
|
||||||
|
@ -1473,7 +1501,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
|
||||||
{
|
{
|
||||||
case LOADORDER_DLL:
|
case LOADORDER_DLL:
|
||||||
TRACE("Trying native dll %s\n", debugstr_w(filename));
|
TRACE("Trying native dll %s\n", debugstr_w(filename));
|
||||||
if (handle == INVALID_HANDLE_VALUE) continue; /* it cannot possibly be loaded */
|
if (!handle) continue; /* it cannot possibly be loaded */
|
||||||
nts = load_native_dll( load_path, filename, handle, flags, pwm );
|
nts = load_native_dll( load_path, filename, handle, flags, pwm );
|
||||||
filetype = "native";
|
filetype = "native";
|
||||||
break;
|
break;
|
||||||
|
@ -1497,7 +1525,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
|
||||||
/* Set the ldr.LoadCount here so that an attach failure will */
|
/* Set the ldr.LoadCount here so that an attach failure will */
|
||||||
/* decrement the dependencies through the MODULE_FreeLibrary call. */
|
/* decrement the dependencies through the MODULE_FreeLibrary call. */
|
||||||
(*pwm)->ldr.LoadCount = 1;
|
(*pwm)->ldr.LoadCount = 1;
|
||||||
if (handle != INVALID_HANDLE_VALUE) NtClose( handle );
|
if (handle) NtClose( handle );
|
||||||
if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
|
if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
|
||||||
return nts;
|
return nts;
|
||||||
}
|
}
|
||||||
|
@ -1505,7 +1533,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
|
||||||
}
|
}
|
||||||
|
|
||||||
WARN("Failed to load module %s; status=%lx\n", debugstr_w(libname), nts);
|
WARN("Failed to load module %s; status=%lx\n", debugstr_w(libname), nts);
|
||||||
if (handle != INVALID_HANDLE_VALUE) NtClose( handle );
|
if (handle) NtClose( handle );
|
||||||
if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
|
if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
|
||||||
return nts;
|
return nts;
|
||||||
}
|
}
|
||||||
|
@ -2007,12 +2035,5 @@ void __wine_process_init( int argc, char *argv[] )
|
||||||
MESSAGE( "wine: could not find __wine_kernel_init in kernel32.dll, status %lx\n", status );
|
MESSAGE( "wine: could not find __wine_kernel_init in kernel32.dll, status %lx\n", status );
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
RtlInitAnsiString( &func_name, "CreateFileW" );
|
|
||||||
if ((status = LdrGetProcedureAddress( wm->ldr.BaseAddress, &func_name,
|
|
||||||
0, (void **)&pCreateFileW )) != STATUS_SUCCESS)
|
|
||||||
{
|
|
||||||
MESSAGE( "wine: could not find CreateFileW in kernel32.dll, status %lx\n", status );
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
init_func();
|
init_func();
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,11 +73,6 @@ extern void SNOOP_SetupDLL( HMODULE hmod );
|
||||||
#define GetCurrentProcessId() ((DWORD)NtCurrentTeb()->ClientId.UniqueProcess)
|
#define GetCurrentProcessId() ((DWORD)NtCurrentTeb()->ClientId.UniqueProcess)
|
||||||
#define GetCurrentThreadId() ((DWORD)NtCurrentTeb()->ClientId.UniqueThread)
|
#define GetCurrentThreadId() ((DWORD)NtCurrentTeb()->ClientId.UniqueThread)
|
||||||
|
|
||||||
/* hack: upcall to kernel */
|
|
||||||
extern HANDLE (WINAPI *pCreateFileW)( LPCWSTR filename, DWORD access, DWORD sharing,
|
|
||||||
LPSECURITY_ATTRIBUTES sa, DWORD creation,
|
|
||||||
DWORD attributes, HANDLE template );
|
|
||||||
|
|
||||||
/* Device IO */
|
/* Device IO */
|
||||||
extern NTSTATUS CDROM_DeviceIoControl(HANDLE hDevice,
|
extern NTSTATUS CDROM_DeviceIoControl(HANDLE hDevice,
|
||||||
HANDLE hEvent, PIO_APC_ROUTINE UserApcRoutine,
|
HANDLE hEvent, PIO_APC_ROUTINE UserApcRoutine,
|
||||||
|
@ -89,6 +84,8 @@ extern NTSTATUS CDROM_DeviceIoControl(HANDLE hDevice,
|
||||||
|
|
||||||
/* file I/O */
|
/* file I/O */
|
||||||
extern NTSTATUS FILE_GetNtStatus(void);
|
extern NTSTATUS FILE_GetNtStatus(void);
|
||||||
|
extern NTSTATUS DIR_nt_to_unix( const UNICODE_STRING *nameW, ANSI_STRING *unix_name_ret,
|
||||||
|
int check_last, int check_case );
|
||||||
|
|
||||||
/* virtual memory */
|
/* virtual memory */
|
||||||
typedef BOOL (*HANDLERPROC)(LPVOID, LPCVOID);
|
typedef BOOL (*HANDLERPROC)(LPVOID, LPCVOID);
|
||||||
|
|
|
@ -40,11 +40,6 @@ static const WCHAR DeviceRootW[] = {'\\','\\','.','\\',0};
|
||||||
static const WCHAR NTDosPrefixW[] = {'\\','?','?','\\',0};
|
static const WCHAR NTDosPrefixW[] = {'\\','?','?','\\',0};
|
||||||
static const WCHAR UncPfxW[] = {'U','N','C','\\',0};
|
static const WCHAR UncPfxW[] = {'U','N','C','\\',0};
|
||||||
|
|
||||||
/* FIXME: hack! */
|
|
||||||
HANDLE (WINAPI *pCreateFileW)( LPCWSTR filename, DWORD access, DWORD sharing,
|
|
||||||
LPSECURITY_ATTRIBUTES sa, DWORD creation,
|
|
||||||
DWORD attributes, HANDLE template );
|
|
||||||
|
|
||||||
#define IS_SEPARATOR(ch) ((ch) == '\\' || (ch) == '/')
|
#define IS_SEPARATOR(ch) ((ch) == '\\' || (ch) == '/')
|
||||||
|
|
||||||
#define MAX_DOS_DRIVES 26
|
#define MAX_DOS_DRIVES 26
|
||||||
|
@ -210,20 +205,6 @@ DOS_PATHNAME_TYPE WINAPI RtlDetermineDosPathNameType_U( PCWSTR path )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************
|
|
||||||
* RtlDoesFileExists_U
|
|
||||||
*
|
|
||||||
* FIXME: should not use CreateFileW
|
|
||||||
*/
|
|
||||||
BOOLEAN WINAPI RtlDoesFileExists_U(LPCWSTR file_name)
|
|
||||||
{
|
|
||||||
HANDLE handle = pCreateFileW( file_name, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
|
|
||||||
NULL, OPEN_EXISTING, 0, 0 );
|
|
||||||
if (handle == INVALID_HANDLE_VALUE) return FALSE;
|
|
||||||
NtClose( handle );
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* RtlIsDosDeviceName_U (NTDLL.@)
|
* RtlIsDosDeviceName_U (NTDLL.@)
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue