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 "wine/unicode.h"
|
||||
#include "wine/server.h"
|
||||
#include "wine/library.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(file);
|
||||
|
@ -71,11 +72,16 @@ typedef struct
|
|||
|
||||
#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, KERNEL_DIRENT [2] )
|
||||
|
||||
#ifndef O_DIRECTORY
|
||||
# define O_DIRECTORY 0200000 /* must be directory */
|
||||
#endif
|
||||
|
||||
#else /* linux */
|
||||
#undef VFAT_IOCTL_READDIR_BOTH /* just in case... */
|
||||
#endif /* linux */
|
||||
|
||||
#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'
|
||||
|
||||
|
@ -572,3 +578,297 @@ NTSTATUS WINAPI NtQueryDirectoryFile( HANDLE handle, HANDLE event,
|
|||
TRACE( "=> %lx (%ld)\n", io->u.Status, io->Information );
|
||||
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.
|
||||
*
|
||||
* PARAMS
|
||||
* FileHandle [O] Variable that receives the file handle on return
|
||||
* DesiredAccess [I] Access desired by the caller to the file
|
||||
* ObjectAttributes [I] Structue describing the file to be opened
|
||||
* IoStatusBlock [O] Receives details about the result of the operation
|
||||
* ShareAccess [I] Type of shared access the caller requires
|
||||
* OpenOptions [I] Options for the file open
|
||||
* handle [O] Variable that receives the file handle on return
|
||||
* access [I] Access desired by the caller to the file
|
||||
* attr [I] Structue describing the file to be opened
|
||||
* io [O] Receives details about the result of the operation
|
||||
* sharing [I] Type of shared access the caller requires
|
||||
* options [I] Options for the file open
|
||||
*
|
||||
* RETURNS
|
||||
* Success: 0. FileHandle and IoStatusBlock are updated.
|
||||
* Failure: An NTSTATUS error code describing the error.
|
||||
*/
|
||||
NTSTATUS WINAPI NtOpenFile(
|
||||
OUT PHANDLE FileHandle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
||||
ULONG ShareAccess,
|
||||
ULONG OpenOptions)
|
||||
NTSTATUS WINAPI NtOpenFile( PHANDLE handle, ACCESS_MASK access,
|
||||
POBJECT_ATTRIBUTES attr, PIO_STATUS_BLOCK io,
|
||||
ULONG sharing, ULONG options )
|
||||
{
|
||||
LPWSTR filename;
|
||||
static const WCHAR szDosDevices[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',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;
|
||||
return NtCreateFile( handle, access, attr, io, NULL, 0,
|
||||
sharing, FILE_OPEN, options, NULL, 0 );
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -127,41 +98,63 @@ NTSTATUS WINAPI NtOpenFile(
|
|||
* directory or volume.
|
||||
*
|
||||
* PARAMS
|
||||
* FileHandle [O] Points to a variable which receives the file handle on return
|
||||
* DesiredAccess [I] Desired access to the file
|
||||
* ObjectAttributes [I] Structure describing the file
|
||||
* IoStatusBlock [O] Receives information about the operation on return
|
||||
* AllocationSize [I] Initial size of the file in bytes
|
||||
* FileAttributes [I] Attributes to create the file with
|
||||
* ShareAccess [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
|
||||
* CreateOptions [I] Options for creating a new file
|
||||
* EaBuffer [I] Undocumented
|
||||
* EaLength [I] Undocumented
|
||||
* handle [O] Points to a variable which receives the file handle on return
|
||||
* access [I] Desired access to the file
|
||||
* attr [I] Structure describing the file
|
||||
* io [O] Receives information about the operation on return
|
||||
* alloc_size [I] Initial size of the file in bytes
|
||||
* attributes [I] Attributes to create the file with
|
||||
* sharing [I] Type of shared access the caller would like to the file
|
||||
* disposition [I] Specifies what to do, depending on whether the file already exists
|
||||
* options [I] Options for creating a new file
|
||||
* ea_buffer [I] Undocumented
|
||||
* ea_length [I] Undocumented
|
||||
*
|
||||
* RETURNS
|
||||
* Success: 0. FileHandle and IoStatusBlock are updated.
|
||||
* Success: 0. handle and io are updated.
|
||||
* Failure: An NTSTATUS error code describing the error.
|
||||
*/
|
||||
NTSTATUS WINAPI NtCreateFile(
|
||||
OUT PHANDLE FileHandle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
||||
PLARGE_INTEGER AllocateSize,
|
||||
ULONG FileAttributes,
|
||||
ULONG ShareAccess,
|
||||
ULONG CreateDisposition,
|
||||
ULONG CreateOptions,
|
||||
PVOID EaBuffer,
|
||||
ULONG EaLength)
|
||||
NTSTATUS WINAPI NtCreateFile( 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 )
|
||||
{
|
||||
FIXME("(%p,0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx) stub\n",
|
||||
FileHandle,DesiredAccess,ObjectAttributes,
|
||||
IoStatusBlock,AllocateSize,FileAttributes,
|
||||
ShareAccess,CreateDisposition,CreateOptions,EaBuffer,EaLength);
|
||||
dump_ObjectAttributes (ObjectAttributes);
|
||||
return 0;
|
||||
ANSI_STRING unix_name;
|
||||
|
||||
TRACE("handle=%p access=%08lx name=%s objattr=%08lx root=%p sec=%p io=%p alloc_size=%p\n"
|
||||
"attr=%08lx sharing=%08lx disp=%ld options=%08lx ea=%p.0x%08lx\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->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 EROFS:
|
||||
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 EMFILE:
|
||||
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,
|
||||
WCHAR *filename, ULONG *size, WINE_MODREF **pwm, HANDLE *handle )
|
||||
{
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
IO_STATUS_BLOCK io;
|
||||
UNICODE_STRING nt_name;
|
||||
WCHAR *file_part, *ext;
|
||||
ULONG len;
|
||||
|
||||
nt_name.Buffer = NULL;
|
||||
if (RtlDetermineDosPathNameType_U( libname ) == RELATIVE_PATH)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
*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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
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;
|
||||
memcpy( filename, nt_name.Buffer + 4, len + sizeof(WCHAR) );
|
||||
if (file_part && !strchrW( file_part, '.' ))
|
||||
{
|
||||
len += sizeof(dllW) - sizeof(WCHAR);
|
||||
if (len >= *size) goto overflow;
|
||||
strcatW( file_part, dllW );
|
||||
strcatW( filename, dllW );
|
||||
}
|
||||
if ((*pwm = find_fullname_module( filename )) != NULL) return STATUS_SUCCESS;
|
||||
*handle = pCreateFileW( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
|
||||
if (!(*pwm = find_fullname_module( filename )))
|
||||
{
|
||||
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;
|
||||
|
||||
overflow:
|
||||
RtlFreeUnicodeString( &nt_name );
|
||||
*size = len + sizeof(WCHAR);
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
@ -1427,7 +1455,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
|
|||
ULONG size;
|
||||
const char *filetype = "";
|
||||
WINE_MODREF *main_exe;
|
||||
HANDLE handle = INVALID_HANDLE_VALUE;
|
||||
HANDLE handle = 0;
|
||||
NTSTATUS nts;
|
||||
|
||||
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:
|
||||
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 );
|
||||
filetype = "native";
|
||||
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 */
|
||||
/* decrement the dependencies through the MODULE_FreeLibrary call. */
|
||||
(*pwm)->ldr.LoadCount = 1;
|
||||
if (handle != INVALID_HANDLE_VALUE) NtClose( handle );
|
||||
if (handle) NtClose( handle );
|
||||
if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
|
||||
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);
|
||||
if (handle != INVALID_HANDLE_VALUE) NtClose( handle );
|
||||
if (handle) NtClose( handle );
|
||||
if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
|
||||
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 );
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -73,11 +73,6 @@ extern void SNOOP_SetupDLL( HMODULE hmod );
|
|||
#define GetCurrentProcessId() ((DWORD)NtCurrentTeb()->ClientId.UniqueProcess)
|
||||
#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 */
|
||||
extern NTSTATUS CDROM_DeviceIoControl(HANDLE hDevice,
|
||||
HANDLE hEvent, PIO_APC_ROUTINE UserApcRoutine,
|
||||
|
@ -89,6 +84,8 @@ extern NTSTATUS CDROM_DeviceIoControl(HANDLE hDevice,
|
|||
|
||||
/* file I/O */
|
||||
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 */
|
||||
typedef BOOL (*HANDLERPROC)(LPVOID, LPCVOID);
|
||||
|
|
|
@ -40,11 +40,6 @@ static const WCHAR DeviceRootW[] = {'\\','\\','.','\\',0};
|
|||
static const WCHAR NTDosPrefixW[] = {'\\','?','?','\\',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 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.@)
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue