Moved support for opening DOS device files to ntdll.

This commit is contained in:
Alexandre Julliard 2004-04-23 03:22:34 +00:00
parent 21b8503c15
commit 223fcdff77
4 changed files with 182 additions and 138 deletions

View File

@ -51,9 +51,6 @@ extern HMODULE kernel32_handle;
extern HANDLE dos_handles[DOS_TABLE_SIZE];
void FILE_ConvertOFMode( INT mode, DWORD *access, DWORD *sharing );
extern HANDLE VOLUME_OpenDevice( LPCWSTR name, DWORD access, DWORD sharing,
LPSECURITY_ATTRIBUTES sa, DWORD attributes );
extern void PTHREAD_Init(void);
extern BOOL WOWTHUNK_Init(void);

View File

@ -66,34 +66,6 @@ enum fs_type
};
/* return default device to use for serial ports */
/* result should not be more than 16 characters long */
static BOOL get_default_com_device( char *buffer, int num )
{
if (!num || num > 9) return FALSE;
#ifdef linux
sprintf( buffer, "/dev/ttyS%d", num - 1 );
return TRUE;
#else
FIXME( "no known default for device com%d\n", num );
return FALSE;
#endif
}
/* return default device to use for parallel ports */
/* result should not be more than 16 characters long */
static BOOL get_default_lpt_device( char *buffer, int num )
{
if (!num || num > 9) return FALSE;
#ifdef linux
sprintf( buffer, "/dev/lp%d", num - 1 );
return TRUE;
#else
FIXME( "no known default for device lpt%d\n", num );
return FALSE;
#endif
}
/* read a Unix symlink; returned buffer must be freed by caller */
static char *read_symlink( const char *path )
{
@ -330,62 +302,6 @@ void VOLUME_CreateDevices(void)
}
/******************************************************************
* VOLUME_OpenDevice
*/
HANDLE VOLUME_OpenDevice( LPCWSTR name, DWORD access, DWORD sharing,
LPSECURITY_ATTRIBUTES sa, DWORD attributes )
{
char *buffer, *dev;
HANDLE ret;
if (!(buffer = get_dos_device_path( name ))) return 0;
dev = strrchr( buffer, '/' ) + 1;
for (;;)
{
TRACE("trying %s\n", buffer );
ret = FILE_CreateFile( buffer, access, sharing, sa, OPEN_EXISTING, attributes, 0 );
if (ret || GetLastError() != ERROR_FILE_NOT_FOUND) break;
if (!dev) break;
/* now try some defaults for it */
if (!strcmp( dev, "aux" ))
{
strcpy( dev, "com1" );
continue;
}
if (!strcmp( dev, "prn" ))
{
strcpy( dev, "lpt1" );
continue;
}
if (!strcmp( dev, "nul" ))
{
strcpy( buffer, "/dev/null" );
dev = NULL; /* last try */
continue;
}
if (!strncmp( dev, "com", 3 ) && get_default_com_device( buffer, dev[3] - '0' ))
{
dev = NULL; /* last try */
continue;
}
if (!strncmp( dev, "lpt", 3 ) && get_default_lpt_device( buffer, dev[3] - '0' ))
{
dev = NULL; /* last try */
continue;
}
break;
}
if (!ret) WARN( "could not open device %s err %ld\n", debugstr_w(name), GetLastError() );
HeapFree( GetProcessHeap(), 0, buffer );
return ret;
}
/******************************************************************
* VOLUME_FindCdRomDataBestVoldesc
*/
@ -1046,12 +962,15 @@ DWORD WINAPI QueryDosDeviceW( LPCWSTR devname, LPWSTR target, DWORD bufsize )
static const WCHAR prnW[] = {'P','R','N',0};
static const WCHAR comW[] = {'C','O','M',0};
static const WCHAR lptW[] = {'L','P','T',0};
static const WCHAR com0W[] = {'C','O','M','0',0};
static const WCHAR rootW[] = {'A',':','\\',0};
static const WCHAR com0W[] = {'\\','?','?','\\','C','O','M','0',0};
static const WCHAR com1W[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\','C','O','M','1',0,0};
static const WCHAR lpt1W[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\','L','P','T','1',0,0};
char buffer[16];
struct stat st;
UNICODE_STRING nt_name;
ANSI_STRING unix_name;
WCHAR nt_buffer[10];
NTSTATUS status;
if (!bufsize)
{
@ -1112,19 +1031,19 @@ DWORD WINAPI QueryDosDeviceW( LPCWSTR devname, LPWSTR target, DWORD bufsize )
return ret;
}
buffer[0] = 0;
if (!strcmpiW( name, nulW ))
strcpy( buffer, "/dev/null" );
else if (!strncmpiW( name, comW, 3 ))
get_default_com_device( buffer, name[3] - '0' );
else if (!strncmpiW( name, lptW, 3 ))
get_default_lpt_device( buffer, name[3] - '0' );
if (buffer[0] && !stat( buffer, &st ))
ret = MultiByteToWideChar( CP_UNIXCP, 0, buffer, -1, target, bufsize );
nt_buffer[0] = '\\';
nt_buffer[1] = '?';
nt_buffer[2] = '?';
nt_buffer[3] = '\\';
strcpyW( nt_buffer + 4, name );
RtlInitUnicodeString( &nt_name, nt_buffer );
status = wine_nt_to_unix_file_name( &nt_name, &unix_name, TRUE, TRUE );
if (status) SetLastError( RtlNtStatusToDosError(status) );
else
SetLastError( ERROR_FILE_NOT_FOUND );
{
ret = MultiByteToWideChar( CP_UNIXCP, 0, unix_name.Buffer, -1, target, bufsize );
RtlFreeAnsiString( &unix_name );
}
}
if (ret)
@ -1138,7 +1057,6 @@ DWORD WINAPI QueryDosDeviceW( LPCWSTR devname, LPWSTR target, DWORD bufsize )
else /* return a list of all devices */
{
WCHAR *p = target;
char *path, *dev, buffer[16];
int i;
if (bufsize <= (sizeof(auxW)+sizeof(nulW)+sizeof(prnW))/sizeof(WCHAR))
@ -1154,15 +1072,15 @@ DWORD WINAPI QueryDosDeviceW( LPCWSTR devname, LPWSTR target, DWORD bufsize )
memcpy( p, prnW, sizeof(prnW) );
p += sizeof(prnW) / sizeof(WCHAR);
if (!(path = get_dos_device_path( com0W ))) return 0;
dev = strrchr( path, '/' ) + 1;
strcpyW( nt_buffer, com0W );
RtlInitUnicodeString( &nt_name, nt_buffer );
for (i = 1; i <= 9; i++)
{
sprintf( dev, "com%d", i );
if (!stat( path, &st ) ||
(get_default_com_device( buffer, i ) && !stat( buffer, &st )))
nt_buffer[7] = '0' + i;
if (!wine_nt_to_unix_file_name( &nt_name, &unix_name, TRUE, TRUE ))
{
RtlFreeAnsiString( &unix_name );
if (p + 5 >= target + bufsize)
{
SetLastError( ERROR_INSUFFICIENT_BUFFER );
@ -1174,12 +1092,13 @@ DWORD WINAPI QueryDosDeviceW( LPCWSTR devname, LPWSTR target, DWORD bufsize )
p += 5;
}
}
strcpyW( nt_buffer + 4, lptW );
for (i = 1; i <= 9; i++)
{
sprintf( dev, "lpt%d", i );
if (!stat( path, &st ) ||
(get_default_lpt_device( buffer, i ) && !stat( buffer, &st )))
nt_buffer[7] = '0' + i;
if (!wine_nt_to_unix_file_name( &nt_name, &unix_name, TRUE, TRUE ))
{
RtlFreeAnsiString( &unix_name );
if (p + 5 >= target + bufsize)
{
SetLastError( ERROR_INSUFFICIENT_BUFFER );
@ -1191,11 +1110,16 @@ DWORD WINAPI QueryDosDeviceW( LPCWSTR devname, LPWSTR target, DWORD bufsize )
p += 5;
}
}
strcpyW( nt_buffer + 4, rootW );
RtlInitUnicodeString( &nt_name, nt_buffer );
for (i = 0; i < 26; i++)
{
sprintf( dev, "%c:", 'a' + i );
if (!stat( path, &st ))
nt_buffer[4] = 'a' + i;
if (!wine_nt_to_unix_file_name( &nt_name, &unix_name, TRUE, TRUE ))
{
RtlFreeAnsiString( &unix_name );
if (p + 3 >= target + bufsize)
{
SetLastError( ERROR_INSUFFICIENT_BUFFER );

View File

@ -140,6 +140,54 @@ static inline off_t telldir_wrapper( DIR *dir, off_t pos, int count )
}
/***********************************************************************
* get_default_com_device
*
* Return the default device to use for serial ports.
*/
static char *get_default_com_device( int num )
{
char *ret = NULL;
if (!num || num > 9) return ret;
#ifdef linux
ret = RtlAllocateHeap( GetProcessHeap(), 0, sizeof("/dev/ttyS0") );
if (ret)
{
strcpy( ret, "/dev/ttyS0" );
ret[strlen(ret) - 1] = '0' + num - 1;
}
#else
FIXME( "no known default for device com%d\n", num );
#endif
return ret;
}
/***********************************************************************
* get_default_lpt_device
*
* Return the default device to use for parallel ports.
*/
static char *get_default_lpt_device( int num )
{
char *ret = NULL;
if (!num || num > 9) return ret;
#ifdef linux
ret = RtlAllocateHeap( GetProcessHeap(), 0, sizeof("/dev/lp0") );
if (ret)
{
strcpy( ret, "/dev/lp0" );
ret[strlen(ret) - 1] = '0' + num - 1;
}
#else
FIXME( "no known default for device lpt%d\n", num );
#endif
return ret;
}
/***********************************************************************
* init_options
*
@ -776,6 +824,97 @@ not_found:
}
/******************************************************************************
* get_dos_device
*
* Get the Unix path of a DOS device.
*/
static NTSTATUS get_dos_device( const WCHAR *name, UINT name_len, ANSI_STRING *unix_name_ret )
{
const char *config_dir = wine_get_config_dir();
struct stat st;
char *unix_name, *dev;
int i, unix_len;
/* make sure the device name is ASCII */
for (i = 0; i < name_len; i++)
if (name[i] <= 32 || name[i] >= 127) return STATUS_OBJECT_NAME_NOT_FOUND;
unix_len = strlen(config_dir) + sizeof("/dosdevices/") + name_len;
if (!(unix_name = RtlAllocateHeap( GetProcessHeap(), 0, unix_len )))
return STATUS_NO_MEMORY;
strcpy( unix_name, config_dir );
strcat( unix_name, "/dosdevices/" );
dev = unix_name + strlen(unix_name);
for (i = 0; i < name_len; i++) dev[i] = (char)tolowerW(name[i]);
dev[i] = 0;
/* special case for drive devices */
if (name_len == 2 && dev[1] == ':') dev[1] = '|';
for (;;)
{
if (!stat( unix_name, &st ))
{
TRACE( "%s -> %s\n", debugstr_wn(name,name_len), 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;
}
if (!dev) break;
/* now try some defaults for it */
if (!strcmp( dev, "aux" ))
{
strcpy( dev, "com1" );
continue;
}
if (!strcmp( dev, "prn" ))
{
strcpy( dev, "lpt1" );
continue;
}
if (!strcmp( dev, "nul" ))
{
strcpy( unix_name, "/dev/null" );
dev = NULL; /* last try */
continue;
}
if (!strncmp( dev, "com", 3 ))
{
char *name = get_default_com_device( dev[3] - '0' );
if (name)
{
RtlFreeHeap( GetProcessHeap(), 0, unix_name );
unix_name = name;
unix_len = strlen(name) + 1;
dev = NULL; /* last try */
continue;
}
}
if (!strncmp( dev, "lpt", 3 ))
{
char *name = get_default_lpt_device( dev[3] - '0' );
if (name)
{
RtlFreeHeap( GetProcessHeap(), 0, unix_name );
unix_name = name;
unix_len = strlen(name) + 1;
dev = NULL; /* last try */
continue;
}
}
break;
}
RtlFreeHeap( GetProcessHeap(), 0, unix_name );
return STATUS_OBJECT_NAME_NOT_FOUND;
}
/* return the length of the DOS namespace prefix if any */
static inline int get_dos_prefix_len( const UNICODE_STRING *name )
{
@ -833,9 +972,13 @@ NTSTATUS wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, ANSI_STRING *un
return STATUS_OBJECT_NAME_NOT_FOUND;
}
/* make sure we have a drive letter */
/* check for a drive letter with path */
if (name_len < 3 || !isalphaW(name[0]) || name[1] != ':' || !IS_SEPARATOR(name[2]))
return STATUS_OBJECT_NAME_NOT_FOUND;
{
/* not a drive with path, try other DOS devices */
return get_dos_device( name, name_len, unix_name_ret );
}
name += 2; /* skip drive letter */
name_len -= 2;

View File

@ -408,15 +408,10 @@ HANDLE WINAPI CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing,
if (dosdev)
{
static const WCHAR conW[] = {'C','O','N',0};
WCHAR dev[5];
static const WCHAR conW[] = {'C','O','N'};
memcpy( dev, filename + HIWORD(dosdev)/sizeof(WCHAR), LOWORD(dosdev) );
dev[LOWORD(dosdev)/sizeof(WCHAR)] = 0;
TRACE("opening device %s\n", debugstr_w(dev) );
if (!strcmpiW( dev, conW ))
if (LOWORD(dosdev) == sizeof(conW) &&
!memicmpW( filename + HIWORD(dosdev)/sizeof(WCHAR), conW, sizeof(conW)))
{
switch (access & (GENERIC_READ|GENERIC_WRITE))
{
@ -431,9 +426,6 @@ HANDLE WINAPI CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing,
return INVALID_HANDLE_VALUE;
}
}
ret = VOLUME_OpenDevice( dev, access, sharing, sa, attributes );
goto done;
}
if (!RtlDosPathNameToNtPathName_U( filename, &nameW, NULL, NULL ))
@ -732,7 +724,6 @@ UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique,
{
static const WCHAR formatW[] = {'%','x','.','t','m','p',0};
DOS_FULL_NAME full_name;
int i;
LPWSTR p;
@ -779,17 +770,6 @@ UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique,
} while (unique != num);
}
/* Get the full path name */
if (DOSFS_GetFullName( buffer, FALSE, &full_name ))
{
char *slash;
/* Check if we have write access in the directory */
if ((slash = strrchr( full_name.long_name, '/' ))) *slash = '\0';
if (access( full_name.long_name, W_OK ) == -1)
WARN("returns %s, which doesn't seem to be writeable.\n",
debugstr_w(buffer) );
}
TRACE("returning %s\n", debugstr_w(buffer) );
return unique;
}