From 223fcdff777632f07560c4fbd5473966dc340f2f Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 23 Apr 2004 03:22:34 +0000 Subject: [PATCH] Moved support for opening DOS device files to ntdll. --- dlls/kernel/kernel_private.h | 3 - dlls/kernel/volume.c | 144 ++++++++-------------------------- dlls/ntdll/directory.c | 147 ++++++++++++++++++++++++++++++++++- files/file.c | 26 +------ 4 files changed, 182 insertions(+), 138 deletions(-) diff --git a/dlls/kernel/kernel_private.h b/dlls/kernel/kernel_private.h index 5054cd70234..dddc7421740 100644 --- a/dlls/kernel/kernel_private.h +++ b/dlls/kernel/kernel_private.h @@ -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); diff --git a/dlls/kernel/volume.c b/dlls/kernel/volume.c index 63dc5ed94c5..ef38eae8ce6 100644 --- a/dlls/kernel/volume.c +++ b/dlls/kernel/volume.c @@ -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 ); diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c index 81ae07bbb00..c1729ad044f 100644 --- a/dlls/ntdll/directory.c +++ b/dlls/ntdll/directory.c @@ -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; diff --git a/files/file.c b/files/file.c index 18d27464ac6..b114ff9e7c7 100644 --- a/files/file.c +++ b/files/file.c @@ -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; }