ntdll / kernel32: #48
Eric Pouech
pouech-eric at wanadoo.fr
Wed Feb 4 14:55:44 CST 2004
Reviewed directory initialisation & management
- now storing system dirs as full & long path names
- rewrote a bit DIR_SearchPath to use better ntdll functions
- nuked DOS_FULL_NAME structure
- in Win NT mode, no longer remember the per drive current directory
- in Win 9x mode, store per drive current directory in =?: environment
variable (? being the drive)
-------------- next part --------------
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel47/kernel_private.h dlls/kernel/kernel_private.h
--- dlls/kernel47/kernel_private.h 2004-01-19 22:42:21.000000000 +0100
+++ dlls/kernel/kernel_private.h 2004-01-20 21:48:28.000000000 +0100
@@ -50,6 +50,9 @@
#define MAX_PATHNAME_LEN 1024
void FILE_ConvertOFMode( INT mode, DWORD *access, DWORD *sharing );
void FILE_SetDosError(void);
+extern DWORD DIR_SearchPath( LPCWSTR path, LPCWSTR name, LPCWSTR ext,
+ LPWSTR full_name, unsigned fnlen, LPWSTR* last, BOOL win32 );
+int DRIVE_GetCurrentDrive(void);
extern void PTHREAD_Init(void);
extern BOOL WOWTHUNK_Init(void);
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel47/process.c dlls/kernel/process.c
--- dlls/kernel47/process.c 2004-01-23 22:37:39.000000000 +0100
+++ dlls/kernel/process.c 2004-01-23 22:40:02.000000000 +0100
@@ -862,13 +862,13 @@
ExitProcess(1);
case BINARY_UNIX_LIB:
{
- DOS_FULL_NAME full_name;
+ char full_name[MAX_PATHNAME_LEN];
TRACE( "starting Winelib app %s\n", debugstr_w(main_exe_name) );
CloseHandle( main_exe_file );
main_exe_file = 0;
- if (DOSFS_GetFullName( main_exe_name, TRUE, &full_name ) &&
- wine_dlopen( full_name.long_name, RTLD_NOW, error, sizeof(error) ))
+ if (wine_get_unix_file_name( main_exe_name, full_name, sizeof(full_name) / sizeof(WCHAR) ) &&
+ wine_dlopen( full_name, RTLD_NOW, error, sizeof(error) ))
{
static const WCHAR soW[] = {'.','s','o',0};
if ((p = strrchrW( main_exe_name, '.' )) && !strcmpW( p, soW ))
@@ -1574,7 +1574,7 @@
BOOL retv = FALSE;
HANDLE hFile = 0;
const char *unixdir = NULL;
- DOS_FULL_NAME full_dir;
+ char full_dir[MAX_PATHNAME_LEN];
WCHAR name[MAX_PATH];
WCHAR *tidy_cmdline, *p, *envW = env;
@@ -1596,15 +1596,15 @@
if (cur_dir)
{
- if (DOSFS_GetFullName( cur_dir, TRUE, &full_dir )) unixdir = full_dir.long_name;
+ if (wine_get_unix_file_name( cur_dir, full_dir, sizeof(full_dir) ))
+ unixdir = full_dir;
}
else
{
WCHAR buf[MAX_PATH];
- if (GetCurrentDirectoryW(MAX_PATH, buf))
- {
- if (DOSFS_GetFullName( buf, TRUE, &full_dir )) unixdir = full_dir.long_name;
- }
+ if (GetCurrentDirectoryW(MAX_PATH, buf) &&
+ wine_get_unix_file_name( buf, full_dir, sizeof(full_dir) ))
+ unixdir = full_dir;
}
if (env && !(flags & CREATE_UNICODE_ENVIRONMENT)) /* convert environment to unicode */
@@ -1682,13 +1682,13 @@
case BINARY_UNIX_EXE:
{
/* unknown file, try as unix executable */
- DOS_FULL_NAME full_name;
+ char uname[MAX_PATH];
TRACE( "starting %s as Unix binary\n", debugstr_w(name) );
- if (DOSFS_GetFullName( name, TRUE, &full_name ))
- retv = (fork_and_exec( full_name.long_name, tidy_cmdline, envW, unixdir ) != -1);
- }
+ if (wine_get_unix_file_name( name, uname, sizeof(uname) ))
+ retv = (fork_and_exec( uname, tidy_cmdline, envW, unixdir ) != -1);
+ }
break;
}
CloseHandle( hFile );
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel47/profile.c dlls/kernel/profile.c
--- dlls/kernel47/profile.c 2004-01-01 09:53:32.000000000 +0100
+++ dlls/kernel/profile.c 2004-01-20 22:30:04.000000000 +0100
@@ -521,7 +521,8 @@
*/
static BOOL PROFILE_Open( LPCWSTR filename )
{
- DOS_FULL_NAME full_name;
+ char full_name[MAX_PATHNAME_LEN];
+ WCHAR short_name[MAX_PATHNAME_LEN];
char buffer[MAX_PATHNAME_LEN];
WCHAR *newdos_name;
WCHAR *name, *name_lwr;
@@ -551,7 +552,8 @@
if (strchrW( filename, '/' ) || strchrW( filename, '\\' ) ||
strchrW( filename, ':' ))
{
- if (!DOSFS_GetFullName( filename, FALSE, &full_name )) return FALSE;
+ if (!wine_get_unix_file_name( filename, full_name, sizeof(full_name) )) return FALSE;
+ GetShortPathNameW(filename, short_name, sizeof(short_name) / sizeof(WCHAR));
}
else
{
@@ -561,13 +563,14 @@
GetWindowsDirectoryW( windirW, MAX_PATH );
strcatW( windirW, bkslashW );
strcatW( windirW, filename );
- if (!DOSFS_GetFullName( windirW, FALSE, &full_name )) return FALSE;
+ if (!wine_get_unix_file_name( windirW, full_name, sizeof(full_name) )) return FALSE;
+ GetShortPathNameW(windirW, short_name, sizeof(short_name) / sizeof(WCHAR));
}
for(i=0;i<N_CACHED_PROFILES;i++)
{
if ((MRUProfile[i]->filename && !strcmpW( filename, MRUProfile[i]->filename )) ||
- (MRUProfile[i]->dos_name && !strcmpW( full_name.short_name, MRUProfile[i]->dos_name )))
+ (MRUProfile[i]->dos_name && !strcmpW( short_name, MRUProfile[i]->dos_name )))
{
if(i)
{
@@ -601,8 +604,8 @@
if(CurProfile->filename) PROFILE_ReleaseFile();
/* OK, now that CurProfile is definitely free we assign it our new file */
- newdos_name = HeapAlloc( GetProcessHeap(), 0, (strlenW(full_name.short_name)+1) * sizeof(WCHAR) );
- strcpyW( newdos_name, full_name.short_name );
+ newdos_name = HeapAlloc( GetProcessHeap(), 0, (strlenW(short_name)+1) * sizeof(WCHAR) );
+ strcpyW( newdos_name, short_name );
CurProfile->dos_name = newdos_name;
CurProfile->filename = HeapAlloc( GetProcessHeap(), 0, (strlenW(filename)+1) * sizeof(WCHAR) );
strcpyW( CurProfile->filename, filename );
@@ -632,11 +635,11 @@
}
else
{
- CurProfile->unix_name = HeapAlloc( GetProcessHeap(), 0, strlen(full_name.long_name)+1 );
- strcpy( CurProfile->unix_name, full_name.long_name );
- if ((file = fopen( full_name.long_name, "r" )))
+ CurProfile->unix_name = HeapAlloc( GetProcessHeap(), 0, strlen(full_name)+1 );
+ strcpy( CurProfile->unix_name, full_name );
+ if ((file = fopen( full_name, "r" )))
TRACE("(%s): found it in %s\n",
- debugstr_w(filename), full_name.long_name );
+ debugstr_w(filename), full_name );
}
if (file)
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel47/task.c dlls/kernel/task.c
--- dlls/kernel47/task.c 2004-01-01 09:53:31.000000000 +0100
+++ dlls/kernel/task.c 2004-01-20 21:45:26.000000000 +0100
@@ -37,8 +37,6 @@
#include "winuser.h"
#include "wine/winbase16.h"
-#include "drive.h"
-#include "file.h"
#include "module.h"
#include "winternl.h"
#include "wine/server.h"
@@ -263,6 +261,7 @@
TDB *pTask;
FARPROC16 proc;
HMODULE16 hModule = pModule ? pModule->self : 0;
+ WCHAR curdirW[MAX_PATH];
/* Allocate the task structure */
@@ -292,7 +291,8 @@
pTask->teb = teb;
pTask->curdrive = DRIVE_GetCurrentDrive() | 0x80;
strcpy( pTask->curdir, "\\" );
- WideCharToMultiByte(CP_ACP, 0, DRIVE_GetDosCwd(DRIVE_GetCurrentDrive()), -1,
+ GetCurrentDirectoryW(sizeof(curdirW), curdirW);
+ WideCharToMultiByte(CP_ACP, 0, curdirW, -1,
pTask->curdir + 1, sizeof(pTask->curdir) - 1, NULL, NULL);
pTask->curdir[sizeof(pTask->curdir) - 1] = 0; /* ensure 0 termination */
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel47/tests/path.c dlls/kernel/tests/path.c
--- dlls/kernel47/tests/path.c 2004-01-17 18:43:51.000000000 +0100
+++ dlls/kernel/tests/path.c 2004-01-20 22:05:58.000000000 +0100
@@ -414,9 +414,9 @@
*/
len=GetCurrentDirectoryA(MAX_PATH,origdir);
ok(len!=0 && len < MAX_PATH,"GetCurrentDirectoryA failed");
- ok(lstrcmpiA(origdir+(len-1),"\\")!=0,
- "GetCurrentDirectoryA should not have a trailing \\");
-/* Make sure that CetCurrentDirectoryA doesn't overwrite the buffer when the
+ ok(len == 3 || lstrcmpiA(origdir+(len-1),"\\")!=0,
+ "GetCurrentDirectoryA should not have a trailing \\ (%s)", origdir);
+/* Make sure that GetCurrentDirectoryA doesn't overwrite the buffer when the
buffer size is too small to hold the current directory
*/
lstrcpyA(tmpstr,"aaaaaaa");
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel47/wowthunk.c dlls/kernel/wowthunk.c
--- dlls/kernel47/wowthunk.c 2004-01-01 09:53:32.000000000 +0100
+++ dlls/kernel/wowthunk.c 2004-01-20 21:47:19.000000000 +0100
@@ -32,7 +32,6 @@
#include "excpt.h"
#include "winreg.h"
#include "winternl.h"
-#include "file.h"
#include "miscemu.h"
#include "module.h"
#include "stackframe.h"
@@ -644,7 +643,7 @@
DWORD WINAPI LoadLibraryEx32W16( LPCSTR lpszLibFile, DWORD hFile, DWORD dwFlags )
{
HMODULE hModule;
- DOS_FULL_NAME full_name;
+ WCHAR tmp[MAX_PATHNAME_LEN];
DWORD mutex_count;
UNICODE_STRING libfileW;
LPCWSTR filenameW;
@@ -666,8 +665,8 @@
a buildin module. This case is handled in MODULE_LoadLibraryExA */
filenameW = libfileW.Buffer;
- if ( DIR_SearchPath( NULL, filenameW, dllW, &full_name, FALSE ) )
- filenameW = full_name.short_name;
+ if ( DIR_SearchPath( NULL, filenameW, dllW, tmp, sizeof(tmp)/sizeof(tmp[0]), NULL, FALSE ) )
+ filenameW = tmp;
ReleaseThunkLock( &mutex_count );
hModule = LoadLibraryExW( filenameW, (HANDLE)hFile, dwFlags );
diff -u -N -r -x '*~' -x '.#*' -x CVS files47/directory.c files/directory.c
--- files47/directory.c 2004-01-18 21:20:00.000000000 +0100
+++ files/directory.c 2004-01-20 22:07:33.000000000 +0100
@@ -45,15 +45,14 @@
#include "winreg.h"
#include "winternl.h"
#include "wine/unicode.h"
-#include "drive.h"
-#include "file.h"
+#include "kernel_private.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dosfs);
WINE_DECLARE_DEBUG_CHANNEL(file);
-static DOS_FULL_NAME DIR_Windows;
-static DOS_FULL_NAME DIR_System;
+static WCHAR DIR_Windows[MAX_PATHNAME_LEN];
+static WCHAR DIR_System[MAX_PATHNAME_LEN];
/***********************************************************************
* FILE_contains_pathW
@@ -69,24 +68,26 @@
*
* Get a path name from the wine.ini file and make sure it is valid.
*/
-static int DIR_GetPath( HKEY hkey, LPCWSTR keyname, LPCWSTR defval, DOS_FULL_NAME *full_name,
- LPWSTR longname, INT longname_len, BOOL warn )
+static int DIR_GetPath( HKEY hkey, LPCWSTR keyname, LPCWSTR defval,
+ LPWSTR shortname, INT shortname_len, BOOL warn )
{
UNICODE_STRING nameW;
- DWORD dummy;
- WCHAR tmp[MAX_PATHNAME_LEN];
- BY_HANDLE_FILE_INFORMATION info;
- const WCHAR *path = defval;
- const char *mess = "does not exist";
+ DWORD dummy, ret, attr;
+ WCHAR tmp[MAX_PATHNAME_LEN];
+ LPCWSTR path = defval;
+ LPCSTR mess = NULL;
RtlInitUnicodeString( &nameW, keyname );
if (hkey && !NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &dummy ))
path = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
- if (!DOSFS_GetFullName( path, TRUE, full_name ) ||
- (!FILE_Stat( full_name->long_name, &info, NULL ) && (mess=strerror(errno)))||
- (!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (mess="not a directory")) ||
- (!(GetLongPathNameW(full_name->short_name, longname, longname_len))) )
+ ret = GetShortPathNameW(path, shortname, shortname_len);
+ if (!ret) mess = "does not exist";
+ else if (ret > shortname_len) mess = "buffer too small";
+ else if ((attr = GetFileAttributesW(shortname)) == INVALID_FILE_ATTRIBUTES)
+ mess = "does not exist";
+ else if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) mess = "not a directory";
+ if (mess != NULL)
{
if (warn)
{
@@ -102,18 +103,91 @@
/***********************************************************************
+ * DIR_FindDriveRoot
+ *
+ * Find a drive for which the root matches the beginning of the given path.
+ * This can be used to translate a Unix path into a drive + DOS path.
+ * Return value is the drive, or -1 on error. On success, path is modified
+ * to point to the beginning of the DOS path.
+ *
+ * Note: path must be in the encoding of the underlying Unix file system.
+ */
+static int DIR_FindDriveRoot( const char **path )
+{
+ /* Starting with the full path, check if the device and inode match any of
+ * the wine 'drives'. If not then remove the last path component and try
+ * again. If the last component was a '..' then skip a normal component
+ * since it's a directory that's ascended back out of.
+ */
+ int drive, level, len;
+ char buffer[MAX_PATHNAME_LEN], t[MAX_PATHNAME_LEN];
+ char *p;
+ struct stat st, dst;
+
+ strcpy( buffer, *path );
+ for (p = buffer; *p; p++) if (*p == '\\') *p = '/';
+ len = p - buffer;
+
+ /* strip off trailing slashes */
+ while (len > 1 && buffer[len - 1] == '/') buffer[--len] = 0;
+
+ for (;;)
+ {
+ /* Find the drive */
+ if (stat( buffer, &st ) == 0 && S_ISDIR( st.st_mode ))
+ {
+ for (drive = 0; drive < 26; drive++)
+ {
+ sprintf(t, "%s/dosdevices/%c:", wine_get_config_dir(), 'a' + drive);
+ if (stat(t, &dst) == -1 || !S_ISDIR(dst.st_mode)) continue;
+
+ if (dst.st_dev == st.st_dev && dst.st_ino == st.st_ino)
+ {
+ if (len == 1) len = 0; /* preserve root slash in returned path */
+ TRACE( "%s -> drive %c:, root='%s', name='%s'\n",
+ *path, 'A' + drive, buffer, *path + len);
+ *path += len;
+ if (!**path) *path = "\\";
+ return drive;
+ }
+ }
+ }
+ if (len <= 1) return -1; /* reached root */
+
+ level = 0;
+ while (level < 1)
+ {
+ /* find start of the last path component */
+ while (len > 1 && buffer[len - 1] != '/') len--;
+ if (!buffer[len]) break; /* empty component -> reached root */
+ /* does removing it take us up a level? */
+ if (strcmp( buffer + len, "." ) != 0)
+ level += strcmp( buffer + len, ".." ) ? 1 : -1;
+ buffer[len] = 0;
+ /* strip off trailing slashes */
+ while (len > 1 && buffer[len - 1] == '/') buffer[--len] = 0;
+ }
+ }
+}
+
+
+/***********************************************************************
* DIR_Init
*/
int DIR_Init(void)
{
- OBJECT_ATTRIBUTES attr;
- UNICODE_STRING nameW;
- HKEY hkey;
- char path[MAX_PATHNAME_LEN];
- WCHAR longpath[MAX_PATHNAME_LEN];
- DOS_FULL_NAME tmp_dir, profile_dir;
- int drive;
- const char *cwd;
+ OBJECT_ATTRIBUTES attr;
+ UNICODE_STRING nameW;
+ HKEY hkey;
+ char path[MAX_PATHNAME_LEN];
+ WCHAR longpath[MAX_PATHNAME_LEN];
+ WCHAR tmp_dir[MAX_PATHNAME_LEN];
+ WCHAR profile_dir[MAX_PATHNAME_LEN];
+ int drive;
+ const char* cwd;
+ int count = 0;
+ WCHAR drive_env[] = {'A',':','\\',0};
+
static const WCHAR wineW[] = {'M','a','c','h','i','n','e','\\',
'S','o','f','t','w','a','r','e','\\',
'W','i','n','e','\\','W','i','n','e','\\',
@@ -138,25 +212,40 @@
static const WCHAR comspecW[] = {'C','O','M','S','P','E','C',0};
static const WCHAR empty_strW[] = { 0 };
+ for (drive_env[0] = 'A'; drive_env[0] <= 'Z'; drive_env[0]++)
+ {
+ if (GetDriveTypeW(drive_env) != DRIVE_NO_ROOT_DIR) count++;
+ }
+
+ if (!count)
+ {
+ MESSAGE("Warning: no valid DOS drive found, check your configuration file.\n" );
+ /* FIXME: should we create a default setting ? */
+ /* Create a C drive pointing to Unix root dir */
+ return 0;
+ }
+
if (!getcwd( path, MAX_PATHNAME_LEN ))
{
perror( "Could not get current directory" );
return 0;
}
cwd = path;
- if ((drive = DRIVE_FindDriveRoot( &cwd )) == -1)
+ if ((drive = DIR_FindDriveRoot( &cwd )) == -1)
{
MESSAGE("Warning: could not find wine config [Drive x] entry "
- "for current working directory %s; "
- "starting in windows directory.\n", cwd );
+ "for current working directory %s; "
+ "starting in windows directory.\n", cwd );
}
else
{
- WCHAR szdrive[3]={drive+'A',':',0};
- MultiByteToWideChar(CP_UNIXCP, 0, cwd, -1, longpath, MAX_PATHNAME_LEN);
- DRIVE_SetCurrentDrive( drive );
- DRIVE_Chdir( drive, longpath );
- if(GetDriveTypeW(szdrive)==DRIVE_CDROM)
+ longpath[0] = drive + 'A';
+ longpath[1] = ':';
+ longpath[2] = '\\';
+ MultiByteToWideChar(CP_UNIXCP, 0, cwd + 1, -1, longpath + 3, MAX_PATHNAME_LEN - 3);
+ SetCurrentDirectoryW(longpath);
+ longpath[2] = '\0';
+ if (GetDriveTypeW(longpath) == DRIVE_CDROM)
chdir("/"); /* change to root directory so as not to lock cdroms */
}
@@ -170,39 +259,40 @@
RtlInitUnicodeString( &nameW, wineW );
if (NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL )) hkey = 0;
- if (!(DIR_GetPath( hkey, windowsW, windows_dirW, &DIR_Windows, longpath, MAX_PATHNAME_LEN, TRUE )) ||
- !(DIR_GetPath( hkey, systemW, system_dirW, &DIR_System, longpath, MAX_PATHNAME_LEN, TRUE )) ||
- !(DIR_GetPath( hkey, tempW, windows_dirW, &tmp_dir, longpath, MAX_PATHNAME_LEN, TRUE )))
+ if (!(DIR_GetPath( hkey, windowsW, windows_dirW, DIR_Windows, MAX_PATHNAME_LEN, TRUE )) ||
+ !(DIR_GetPath( hkey, systemW, system_dirW, DIR_System, MAX_PATHNAME_LEN, TRUE )) ||
+ !(DIR_GetPath( hkey, tempW, windows_dirW, tmp_dir, MAX_PATHNAME_LEN, TRUE )))
{
if (hkey) NtClose( hkey );
return 0;
}
- if (-1 == access( tmp_dir.long_name, W_OK ))
+ if (!wine_get_unix_file_name(tmp_dir, path, MAX_PATHNAME_LEN))
{
- if (errno==EACCES)
- {
- MESSAGE("Warning: the temporary directory '%s' specified in your\n"
+ if (access( path, W_OK ) == -1)
+ {
+ if (errno == EACCES)
+ {
+ MESSAGE("Warning: the temporary directory '%s' specified in your\n"
"configuration file (%s) is not writeable.\n",
- tmp_dir.long_name, wine_get_config_dir() );
- }
- else
- MESSAGE("Warning: access to temporary directory '%s' failed (%s).\n",
- tmp_dir.long_name, strerror(errno));
+ path, wine_get_config_dir() );
+ }
+ else
+ MESSAGE("Warning: access to temporary directory '%s' failed (%s).\n",
+ path, strerror(errno));
+ }
+ else
+ MESSAGE("Warning: access to temporary directory '%s' failed (%s).\n",
+ debugstr_w(tmp_dir), strerror(errno));
}
- if (drive == -1)
- {
- drive = DIR_Windows.drive;
- DRIVE_SetCurrentDrive( drive );
- DRIVE_Chdir( drive, DIR_Windows.short_name + 2 );
- }
+ if (drive == -1) SetCurrentDirectoryW( DIR_Windows );
/* Set the environment variables */
/* set COMSPEC only if it doesn't exist already */
if (!GetEnvironmentVariableW( comspecW, NULL, 0 ))
{
- strcpyW( longpath, DIR_System.short_name );
+ strcpyW( longpath, DIR_System );
strcatW( longpath, wcmdW );
SetEnvironmentVariableW( comspecW, longpath );
}
@@ -212,46 +302,48 @@
{
WCHAR tmp[MAX_PATHNAME_LEN];
DWORD dummy;
- const WCHAR *path = path_dirW;
+ const WCHAR *lpathW = path_dirW;
RtlInitUnicodeString( &nameW, pathW );
if (hkey && !NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
tmp, sizeof(tmp), &dummy ))
{
- path = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
+ lpathW = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
}
- if (strchrW(path, '/'))
+ if (strchrW(lpathW, '/'))
{
MESSAGE("Fix your wine config (%s/config) to use DOS drive syntax in [wine] 'Path=' statement! (no '/' allowed)\n", wine_get_config_dir() );
ExitProcess(1);
}
- SetEnvironmentVariableW( path_capsW, path );
- TRACE("Path = %s\n", debugstr_w(path) );
+ SetEnvironmentVariableW( path_capsW, lpathW );
+ TRACE("Path = %s\n", debugstr_w(lpathW) );
}
- SetEnvironmentVariableW( temp_capsW, tmp_dir.short_name );
- SetEnvironmentVariableW( tmp_capsW, tmp_dir.short_name );
- SetEnvironmentVariableW( windirW, DIR_Windows.short_name );
- SetEnvironmentVariableW( winsysdirW, DIR_System.short_name );
-
- TRACE("WindowsDir = %s (%s)\n",
- debugstr_w(DIR_Windows.short_name), DIR_Windows.long_name );
- TRACE("SystemDir = %s (%s)\n",
- debugstr_w(DIR_System.short_name), DIR_System.long_name );
- TRACE("TempDir = %s (%s)\n",
- debugstr_w(tmp_dir.short_name), tmp_dir.long_name );
- TRACE("Cwd = %c:\\%s\n",
- 'A' + drive, debugstr_w(DRIVE_GetDosCwd(drive)) );
+ SetEnvironmentVariableW( temp_capsW, tmp_dir );
+ SetEnvironmentVariableW( tmp_capsW, tmp_dir );
+ SetEnvironmentVariableW( windirW, DIR_Windows );
+ SetEnvironmentVariableW( winsysdirW, DIR_System );
+
+ if (TRACE_ON(dosfs))
+ {
+ char tmp[MAX_PATHNAME_LEN];
+ wine_get_unix_file_name(DIR_Windows, tmp, sizeof(tmp));
+ TRACE("WindowsDir = %s (%s)\n", debugstr_w(DIR_Windows), tmp );
+ wine_get_unix_file_name(DIR_System, tmp, sizeof(tmp));
+ TRACE("SystemDir = %s (%s)\n", debugstr_w(DIR_System), tmp );
+ wine_get_unix_file_name(tmp_dir, tmp, sizeof(tmp));
+ TRACE("TempDir = %s (%s)\n", debugstr_w(tmp_dir), tmp );
+ }
- if (DIR_GetPath( hkey, profileW, empty_strW, &profile_dir, longpath, MAX_PATHNAME_LEN, FALSE ))
+ if (DIR_GetPath( hkey, profileW, empty_strW, profile_dir, MAX_PATHNAME_LEN, FALSE ))
{
TRACE("USERPROFILE= %s\n", debugstr_w(longpath) );
SetEnvironmentVariableW( userprofileW, longpath );
}
- TRACE("SYSTEMROOT = %s\n", debugstr_w(DIR_Windows.short_name) );
- SetEnvironmentVariableW( systemrootW, DIR_Windows.short_name );
+ TRACE("SYSTEMROOT = %s\n", debugstr_w(DIR_Windows) );
+ SetEnvironmentVariableW( systemrootW, DIR_Windows );
if (hkey) NtClose( hkey );
return 1;
@@ -340,27 +432,6 @@
return ret;
}
-
-/***********************************************************************
- * DIR_GetWindowsUnixDir
- */
-UINT DIR_GetWindowsUnixDir( LPSTR path, UINT count )
-{
- if (path) lstrcpynA( path, DIR_Windows.long_name, count );
- return strlen( DIR_Windows.long_name );
-}
-
-
-/***********************************************************************
- * DIR_GetSystemUnixDir
- */
-UINT DIR_GetSystemUnixDir( LPSTR path, UINT count )
-{
- if (path) lstrcpynA( path, DIR_System.long_name, count );
- return strlen( DIR_System.long_name );
-}
-
-
/***********************************************************************
* GetTempDrive (KERNEL.92)
* A closer look at krnl386.exe shows what the SDK doesn't mention:
@@ -406,10 +477,10 @@
*/
UINT WINAPI GetWindowsDirectoryW( LPWSTR path, UINT count )
{
- UINT len = strlenW( DIR_Windows.short_name ) + 1;
+ UINT len = strlenW( DIR_Windows ) + 1;
if (path && count >= len)
{
- strcpyW( path, DIR_Windows.short_name );
+ strcpyW( path, DIR_Windows );
len--;
}
return len;
@@ -427,10 +498,10 @@
*/
UINT WINAPI GetWindowsDirectoryA( LPSTR path, UINT count )
{
- UINT len = WideCharToMultiByte( CP_ACP, 0, DIR_Windows.short_name, -1, NULL, 0, NULL, NULL );
+ UINT len = WideCharToMultiByte( CP_ACP, 0, DIR_Windows, -1, NULL, 0, NULL, NULL );
if (path && count >= len)
{
- WideCharToMultiByte( CP_ACP, 0, DIR_Windows.short_name, -1, path, count, NULL, NULL );
+ WideCharToMultiByte( CP_ACP, 0, DIR_Windows, -1, path, count, NULL, NULL );
len--;
}
return len;
@@ -471,10 +542,10 @@
*/
UINT WINAPI GetSystemDirectoryW( LPWSTR path, UINT count )
{
- UINT len = strlenW( DIR_System.short_name ) + 1;
+ UINT len = strlenW( DIR_System ) + 1;
if (path && count >= len)
{
- strcpyW( path, DIR_System.short_name );
+ strcpyW( path, DIR_System );
len--;
}
return len;
@@ -488,10 +559,10 @@
*/
UINT WINAPI GetSystemDirectoryA( LPSTR path, UINT count )
{
- UINT len = WideCharToMultiByte( CP_ACP, 0, DIR_System.short_name, -1, NULL, 0, NULL, NULL );
+ UINT len = WideCharToMultiByte( CP_ACP, 0, DIR_System, -1, NULL, 0, NULL, NULL );
if (path && count >= len)
{
- WideCharToMultiByte( CP_ACP, 0, DIR_System.short_name, -1, path, count, NULL, NULL );
+ WideCharToMultiByte( CP_ACP, 0, DIR_System, -1, path, count, NULL, NULL );
len--;
}
return len;
@@ -519,9 +590,9 @@
* ERROR_FILENAME_EXCED_RANGE: too long filename(s)
*/
BOOL WINAPI CreateDirectoryW( LPCWSTR path,
- LPSECURITY_ATTRIBUTES lpsecattribs )
+ LPSECURITY_ATTRIBUTES lpsecattribs )
{
- DOS_FULL_NAME full_name;
+ char uname[MAX_PATH];
if (!path || !*path)
{
@@ -534,25 +605,38 @@
if (RtlIsDosDeviceName_U( path ))
{
TRACE_(file)("cannot use device %s!\n", debugstr_w(path));
- SetLastError( ERROR_ACCESS_DENIED );
+ SetLastError(ERROR_ACCESS_DENIED);
return FALSE;
}
- if (!DOSFS_GetFullName( path, FALSE, &full_name )) return 0;
- if (mkdir( full_name.long_name, 0777 ) == -1) {
- WARN_(file)("Error '%s' trying to create directory '%s'\n", strerror(errno), full_name.long_name);
+ if (!wine_get_unix_file_name(path, uname, sizeof(uname)))
+ {
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ return FALSE;
+ }
+ if (mkdir(uname, 0777) == -1)
+ {
+ WARN_(file)("Error '%s' trying to create directory '%s'\n", strerror(errno), uname);
/* the FILE_SetDosError() generated error codes don't match the
* CreateDirectory ones for some errnos */
- switch (errno) {
- case EEXIST:
+ switch (errno)
{
- if (!strcmp(DRIVE_GetRoot(full_name.drive), full_name.long_name))
- SetLastError(ERROR_ACCESS_DENIED);
- else
- SetLastError(ERROR_ALREADY_EXISTS);
+ case EEXIST:
+ {
+ WCHAR x[MAX_PATH];
+ if (!RtlGetFullPathName_U(path, sizeof(x), x, NULL))
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ else if (strlenW(x) <= 3)
+ SetLastError(ERROR_ACCESS_DENIED);
+ else
+ SetLastError(ERROR_ALREADY_EXISTS);
+ }
+ break;
+ case ENOSPC:
+ SetLastError(ERROR_DISK_FULL);
+ break;
+ default:
+ FILE_SetDosError();
break;
- }
- case ENOSPC: SetLastError(ERROR_DISK_FULL); break;
- default: FILE_SetDosError();break;
}
return FALSE;
}
@@ -590,7 +674,7 @@
* CreateDirectoryExA (KERNEL32.@)
*/
BOOL WINAPI CreateDirectoryExA( LPCSTR template, LPCSTR path,
- LPSECURITY_ATTRIBUTES lpsecattribs)
+ LPSECURITY_ATTRIBUTES lpsecattribs)
{
return CreateDirectoryA(path,lpsecattribs);
}
@@ -600,7 +684,7 @@
* CreateDirectoryExW (KERNEL32.@)
*/
BOOL WINAPI CreateDirectoryExW( LPCWSTR template, LPCWSTR path,
- LPSECURITY_ATTRIBUTES lpsecattribs)
+ LPSECURITY_ATTRIBUTES lpsecattribs)
{
return CreateDirectoryW(path,lpsecattribs);
}
@@ -620,7 +704,7 @@
*/
BOOL WINAPI RemoveDirectoryW( LPCWSTR path )
{
- DOS_FULL_NAME full_name;
+ char buffer[MAX_PATH];
if (!path)
{
@@ -636,8 +720,12 @@
SetLastError( ERROR_FILE_NOT_FOUND );
return FALSE;
}
- if (!DOSFS_GetFullName( path, TRUE, &full_name )) return FALSE;
- if (rmdir( full_name.long_name ) == -1)
+ if (!wine_get_unix_file_name( path, buffer, sizeof(buffer) ))
+ {
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ return FALSE;
+ }
+ if (rmdir( buffer ) == -1)
{
FILE_SetDosError();
return FALSE;
@@ -672,131 +760,6 @@
/***********************************************************************
- * DIR_TryPath
- *
- * Helper function for DIR_SearchPath.
- */
-static BOOL DIR_TryPath( const DOS_FULL_NAME *dir, LPCWSTR name,
- DOS_FULL_NAME *full_name )
-{
- LPSTR p_l = full_name->long_name + strlen(dir->long_name) + 1;
- LPWSTR p_s = full_name->short_name + strlenW(dir->short_name) + 1;
-
- if ((p_s >= full_name->short_name + sizeof(full_name->short_name)/sizeof(full_name->short_name[0]) - 14) ||
- (p_l >= full_name->long_name + sizeof(full_name->long_name) - 1))
- {
- SetLastError( ERROR_PATH_NOT_FOUND );
- return FALSE;
- }
- if (!DOSFS_FindUnixName( dir, name, p_l,
- sizeof(full_name->long_name) - (p_l - full_name->long_name),
- p_s, !(DRIVE_GetFlags(dir->drive) & DRIVE_CASE_SENSITIVE) ))
- return FALSE;
-
- full_name->drive = dir->drive;
- strcpy( full_name->long_name, dir->long_name );
- p_l[-1] = '/';
- strcpyW( full_name->short_name, dir->short_name );
- p_s[-1] = '\\';
- return TRUE;
-}
-
-static BOOL DIR_SearchSemicolonedPaths(LPCWSTR name, DOS_FULL_NAME *full_name, LPWSTR pathlist)
-{
- LPWSTR next, buffer = NULL;
- INT len = strlenW(name), newlen, currlen = 0;
- BOOL ret = FALSE;
-
- next = pathlist;
- while (!ret && next)
- {
- static const WCHAR bkslashW[] = {'\\',0};
- LPWSTR cur = next;
- while (*cur == ';') cur++;
- if (!*cur) break;
- next = strchrW( cur, ';' );
- if (next) *next++ = '\0';
- newlen = strlenW(cur) + len + 2;
-
- if (newlen > currlen)
- {
- if (buffer)
- buffer = HeapReAlloc( GetProcessHeap(), 0, buffer, newlen * sizeof(WCHAR));
- else
- buffer = HeapAlloc( GetProcessHeap(), 0, newlen * sizeof(WCHAR));
-
- if(!buffer)
- goto done;
- currlen = newlen;
- }
-
- strcpyW( buffer, cur );
- strcatW( buffer, bkslashW );
- strcatW( buffer, name );
- ret = DOSFS_GetFullName( buffer, TRUE, full_name );
- }
-done:
- HeapFree( GetProcessHeap(), 0, buffer );
- return ret;
-}
-
-
-/***********************************************************************
- * DIR_TryEnvironmentPath
- *
- * Helper function for DIR_SearchPath.
- * Search in the specified path, or in $PATH if NULL.
- */
-static BOOL DIR_TryEnvironmentPath( LPCWSTR name, DOS_FULL_NAME *full_name, LPCWSTR envpath )
-{
- LPWSTR path;
- BOOL ret = FALSE;
- DWORD size;
- static const WCHAR pathW[] = {'P','A','T','H',0};
-
- size = envpath ? strlenW(envpath)+1 : GetEnvironmentVariableW( pathW, NULL, 0 );
- if (!size) return FALSE;
- if (!(path = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return FALSE;
- if (envpath) strcpyW( path, envpath );
- else if (!GetEnvironmentVariableW( pathW, path, size )) goto done;
-
- ret = DIR_SearchSemicolonedPaths(name, full_name, path);
-
-done:
- HeapFree( GetProcessHeap(), 0, path );
- return ret;
-}
-
-
-/***********************************************************************
- * DIR_TryModulePath
- *
- * Helper function for DIR_SearchPath.
- */
-static BOOL DIR_TryModulePath( LPCWSTR name, DOS_FULL_NAME *full_name, BOOL win32 )
-{
- WCHAR bufferW[MAX_PATH];
- LPWSTR p;
-
- if (!win32)
- {
- char buffer[OFS_MAXPATHNAME];
- if (!GetCurrentTask()) return FALSE;
- if (!GetModuleFileName16( GetCurrentTask(), buffer, sizeof(buffer) ))
- return FALSE;
- MultiByteToWideChar(CP_ACP, 0, buffer, -1, bufferW, MAX_PATH);
- } else {
- if (!GetModuleFileNameW( 0, bufferW, MAX_PATH )) return FALSE;
- bufferW[MAX_PATH - 1] = '\0';
- }
- if (!(p = strrchrW( bufferW, '\\' ))) return FALSE;
- if (MAX_PATH - (++p - bufferW) <= strlenW(name)) return FALSE;
- strcpyW( p, name );
- return DOSFS_GetFullName( bufferW, TRUE, full_name );
-}
-
-
-/***********************************************************************
* DIR_SearchPath
*
* Implementation of SearchPathA. 'win32' specifies whether the search
@@ -805,11 +768,12 @@
* FIXME: should return long path names.
*/
DWORD DIR_SearchPath( LPCWSTR path, LPCWSTR name, LPCWSTR ext,
- DOS_FULL_NAME *full_name, BOOL win32 )
+ LPWSTR fullname, unsigned fnlen, LPWSTR* last, BOOL win32 )
{
- LPCWSTR p;
- LPWSTR tmp = NULL;
- BOOL ret = TRUE;
+ LPCWSTR p;
+ LPWSTR tmp = NULL, ev;
+ DWORD ret = 0, size;
+ static const WCHAR pathW[] = {'P','A','T','H',0};
/* First check the supplied parameters */
@@ -839,7 +803,19 @@
if (FILE_contains_pathW(name))
{
- ret = DOSFS_GetFullName( name, TRUE, full_name );
+ if (*name == '/')
+ {
+ ret = strlenW(name);
+ if (ret >= fnlen)
+ {
+ SetLastError(ERROR_BUFFER_OVERFLOW);
+ goto done;
+ }
+ strcpyW(fullname, name);
+ }
+ else ret = GetFullPathNameW(name, fnlen, fullname, last);
+
+ if (!RtlDoesFileExists_U(fullname)) ret = 0;
goto done;
}
@@ -847,38 +823,58 @@
if (path)
{
- ret = DIR_TryEnvironmentPath( name, full_name, path );
+ ret = RtlDosSearchPath_U(path, name, NULL, fnlen, fullname, last);
goto done;
}
/* Try the path of the current executable (for Win32 search order) */
-
- if (win32 && DIR_TryModulePath( name, full_name, win32 )) goto done;
+ if (win32)
+ {
+ WCHAR bufferW[MAX_PATH];
+ if (GetModuleFileNameW(0, bufferW, MAX_PATH ) &&
+ (ret = RtlDosSearchPath_U(bufferW, name, NULL, fnlen, fullname, last)))
+ goto done;
+ }
/* Try the current directory */
-
- if (DOSFS_GetFullName( name, TRUE, full_name )) goto done;
+ if ((ret = GetFullPathNameW(name, fnlen, fullname, last)) &&
+ RtlDoesFileExists_U(fullname)) goto done;
/* Try the Windows system directory */
-
- if (DIR_TryPath( &DIR_System, name, full_name ))
+ if ((ret = RtlDosSearchPath_U(DIR_System, name, NULL, fnlen, fullname, last)))
goto done;
/* Try the Windows directory */
-
- if (DIR_TryPath( &DIR_Windows, name, full_name ))
+ if ((ret = RtlDosSearchPath_U(DIR_Windows, name, NULL, fnlen, fullname, last)))
goto done;
/* Try the path of the current executable (for Win16 search order) */
+ if (!win32)
+ {
+ char buffer[OFS_MAXPATHNAME];
+ WCHAR bufferW[MAX_PATH];
- if (!win32 && DIR_TryModulePath( name, full_name, win32 )) goto done;
+ if (GetCurrentTask() &&
+ GetModuleFileName16(GetCurrentTask(), buffer, sizeof(buffer)))
+ {
+ MultiByteToWideChar(CP_ACP, 0, buffer, -1, bufferW, MAX_PATH);
+ if ((ret = RtlDosSearchPath_U(bufferW, name, NULL, fnlen, fullname, last)))
+ goto done;
+ }
+ }
/* Try all directories in path */
-
- ret = DIR_TryEnvironmentPath( name, full_name, NULL );
+ if ((size = GetEnvironmentVariableW(pathW, NULL, 0)) &&
+ (ev = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR))))
+ {
+ GetEnvironmentVariableW(pathW, ev, size);
+ ret = RtlDosSearchPath_U(ev, name, NULL, fnlen, fullname, last);
+ HeapFree(GetProcessHeap(), 0, ev);
+ }
done:
if (tmp) HeapFree( GetProcessHeap(), 0, tmp );
+ if (!ret) SetLastError(ERROR_FILE_NOT_FOUND);
return ret;
}
@@ -914,35 +910,15 @@
DWORD WINAPI SearchPathW( LPCWSTR path, LPCWSTR name, LPCWSTR ext, DWORD buflen,
LPWSTR buffer, LPWSTR *lastpart )
{
- LPSTR res;
- DOS_FULL_NAME full_name;
+ DWORD ret;
- if (!DIR_SearchPath( path, name, ext, &full_name, TRUE ))
- {
- SetLastError(ERROR_FILE_NOT_FOUND);
- return 0;
- }
+ TRACE("%s %s %s %lu %p %p\n",
+ debugstr_w(path), debugstr_w(name), debugstr_w(ext),
+ buflen, buffer, lastpart);
+ ret = DIR_SearchPath( path, name, ext, buffer, buflen, lastpart, TRUE );
-TRACE("found %s %s\n", full_name.long_name, debugstr_w(full_name.short_name));
-TRACE("drive %c: root %s\n", 'A' + full_name.drive, DRIVE_GetRoot(full_name.drive));
-
- lstrcpynW( buffer, full_name.short_name, buflen );
- res = full_name.long_name +
- strlen(DRIVE_GetRoot( full_name.drive ));
- while (*res == '/') res++;
- if (buflen)
- {
- LPWSTR p;
- if (buflen > 3)
- {
- MultiByteToWideChar(CP_UNIXCP, 0, res, -1, buffer + 3, buflen - 3);
- buffer[buflen - 1] = 0;
- }
- for (p = buffer; *p; p++) if (*p == '/') *p = '\\';
- if (lastpart) *lastpart = strrchrW( buffer, '\\' ) + 1;
- }
TRACE("Returning %s\n", debugstr_w(buffer) );
- return strlenW(buffer);
+ return ret;
}
diff -u -N -r -x '*~' -x '.#*' -x CVS files47/dos_fs.c files/dos_fs.c
--- files47/dos_fs.c 2004-01-23 22:38:38.000000000 +0100
+++ files/dos_fs.c 2004-01-23 22:42:48.000000000 +0100
@@ -106,50 +106,6 @@
} DOS_DIR;
/***********************************************************************
- * DOSFS_ValidDOSName
- *
- * Return 1 if Unix file 'name' is also a valid MS-DOS name
- * (i.e. contains only valid DOS chars, lower-case only, fits in 8.3 format).
- * File name can be terminated by '\0', '\\' or '/'.
- */
-static int DOSFS_ValidDOSName( LPCWSTR name, int ignore_case )
-{
- static const char invalid_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" INVALID_DOS_CHARS;
- const WCHAR *p = name;
- const char *invalid = ignore_case ? (invalid_chars + 26) : invalid_chars;
- int len = 0;
-
- if (*p == '.')
- {
- /* Check for "." and ".." */
- p++;
- if (*p == '.') p++;
- /* All other names beginning with '.' are invalid */
- return (IS_END_OF_NAME(*p));
- }
- while (!IS_END_OF_NAME(*p))
- {
- if (*p < 256 && strchr( invalid, (char)*p )) return 0; /* Invalid char */
- if (*p == '.') break; /* Start of the extension */
- if (++len > 8) return 0; /* Name too long */
- p++;
- }
- if (*p != '.') return 1; /* End of name */
- p++;
- if (IS_END_OF_NAME(*p)) return 0; /* Empty extension not allowed */
- len = 0;
- while (!IS_END_OF_NAME(*p))
- {
- if (*p < 256 && strchr( invalid, (char)*p )) return 0; /* Invalid char */
- if (*p == '.') return 0; /* Second extension not allowed */
- if (++len > 3) return 0; /* Extension too long */
- p++;
- }
- return 1;
-}
-
-
-/***********************************************************************
* DOSFS_ToDosFCBFormat
*
* Convert a file name to DOS FCB format (8+3 chars, padded with blanks),
@@ -250,598 +206,6 @@
/***********************************************************************
- * DOSFS_ToDosDTAFormat
- *
- * Convert a file name from FCB to DTA format (name.ext, null-terminated)
- * converting to upper-case in the process.
- * File name can be terminated by '\0', '\\' or '/'.
- * 'buffer' must be at least 13 characters long.
- */
-static void DOSFS_ToDosDTAFormat( LPCWSTR name, LPWSTR buffer )
-{
- LPWSTR p;
-
- memcpy( buffer, name, 8 * sizeof(WCHAR) );
- p = buffer + 8;
- while ((p > buffer) && (p[-1] == ' ')) p--;
- *p++ = '.';
- memcpy( p, name + 8, 3 * sizeof(WCHAR) );
- p += 3;
- while (p[-1] == ' ') p--;
- if (p[-1] == '.') p--;
- *p = '\0';
-}
-
-
-/***********************************************************************
- * DOSFS_AddDirEntry
- *
- * Used to construct an array of filenames in DOSFS_OpenDir
- */
-static BOOL DOSFS_AddDirEntry(DOS_DIR **dir, LPCWSTR name, LPCWSTR dosname)
-{
- int extra1 = strlenW(name) + 1;
- int extra2 = strlenW(dosname) + 1;
-
- /* if we need more, at minimum double the size */
- if( (extra1 + extra2 + (*dir)->used) > (*dir)->size)
- {
- int more = (*dir)->size;
- DOS_DIR *t;
-
- if(more<(extra1+extra2))
- more = extra1+extra2;
-
- t = HeapReAlloc(GetProcessHeap(), 0, *dir, sizeof(**dir) +
- ((*dir)->size + more)*sizeof(WCHAR) );
- if(!t)
- {
- SetLastError( ERROR_NOT_ENOUGH_MEMORY );
- ERR("Out of memory caching directory structure %d %d %d\n",
- (*dir)->size, more, (*dir)->used);
- return FALSE;
- }
- (*dir) = t;
- (*dir)->size += more;
- }
-
- /* at this point, the dir structure is big enough to hold these names */
- strcpyW(&(*dir)->names[(*dir)->used], name);
- (*dir)->used += extra1;
- strcpyW(&(*dir)->names[(*dir)->used], dosname);
- (*dir)->used += extra2;
-
- return TRUE;
-}
-
-
-/***********************************************************************
- * DOSFS_OpenDir_VFAT
- */
-static BOOL DOSFS_OpenDir_VFAT(DOS_DIR **dir, const char *unix_path)
-{
-#ifdef VFAT_IOCTL_READDIR_BOTH
- KERNEL_DIRENT de[2];
- int fd = open( unix_path, O_RDONLY|O_DIRECTORY );
- BOOL r = TRUE;
-
- /* Check if the VFAT ioctl is supported on this directory */
-
- if ( fd<0 )
- return FALSE;
-
- while (1)
- {
- WCHAR long_name[MAX_PATH];
- WCHAR short_name[12];
-
- r = (ioctl( fd, VFAT_IOCTL_READDIR_BOTH, (long)de ) != -1);
- if(!r)
- break;
- if (!de[0].d_reclen)
- break;
- MultiByteToWideChar(CP_UNIXCP, 0, de[0].d_name, -1, long_name, MAX_PATH);
- if (!DOSFS_ToDosFCBFormat( long_name, short_name ))
- short_name[0] = '\0';
- if (de[1].d_name[0])
- MultiByteToWideChar(CP_UNIXCP, 0, de[1].d_name, -1, long_name, MAX_PATH);
- else
- MultiByteToWideChar(CP_UNIXCP, 0, de[0].d_name, -1, long_name, MAX_PATH);
- r = DOSFS_AddDirEntry(dir, long_name, short_name );
- if(!r)
- break;
- }
- if(r)
- {
- static const WCHAR empty_strW[] = { 0 };
- DOSFS_AddDirEntry(dir, empty_strW, empty_strW);
- }
- close(fd);
- return r;
-#else
- return FALSE;
-#endif /* VFAT_IOCTL_READDIR_BOTH */
-}
-
-
-/***********************************************************************
- * DOSFS_OpenDir_Normal
- *
- * Now use the standard opendir/readdir interface
- */
-static BOOL DOSFS_OpenDir_Normal( DOS_DIR **dir, const char *unix_path )
-{
- DIR *unixdir = opendir( unix_path );
- BOOL r = TRUE;
- static const WCHAR empty_strW[] = { 0 };
-
- if(!unixdir)
- return FALSE;
- while(1)
- {
- WCHAR long_name[MAX_PATH];
- struct dirent *de = readdir(unixdir);
-
- if(!de)
- break;
- MultiByteToWideChar(CP_UNIXCP, 0, de->d_name, -1, long_name, MAX_PATH);
- r = DOSFS_AddDirEntry(dir, long_name, empty_strW);
- if(!r)
- break;
- }
- if(r)
- DOSFS_AddDirEntry(dir, empty_strW, empty_strW);
- closedir(unixdir);
- return r;
-}
-
-/***********************************************************************
- * DOSFS_OpenDir
- */
-static DOS_DIR *DOSFS_OpenDir( const char *unix_path )
-{
- const int init_size = 0x100;
- DOS_DIR *dir = HeapAlloc( GetProcessHeap(), 0, sizeof(*dir) + init_size*sizeof (WCHAR));
- BOOL r;
-
- TRACE("%s\n",debugstr_a(unix_path));
-
- if (!dir)
- {
- SetLastError( ERROR_NOT_ENOUGH_MEMORY );
- return NULL;
- }
- dir->used = 0;
- dir->size = init_size;
-
- /* Treat empty path as root directory. This simplifies path split into
- directory and mask in several other places */
- if (!*unix_path) unix_path = "/";
-
- r = DOSFS_OpenDir_VFAT( &dir, unix_path);
-
- if(!r)
- r = DOSFS_OpenDir_Normal( &dir, unix_path);
-
- if(!r)
- {
- HeapFree(GetProcessHeap(), 0, dir);
- return NULL;
- }
- dir->used = 0;
-
- return dir;
-}
-
-
-/***********************************************************************
- * DOSFS_CloseDir
- */
-static void DOSFS_CloseDir( DOS_DIR *dir )
-{
- HeapFree( GetProcessHeap(), 0, dir );
-}
-
-
-/***********************************************************************
- * DOSFS_ReadDir
- */
-static BOOL DOSFS_ReadDir( DOS_DIR *dir, LPCWSTR *long_name,
- LPCWSTR *short_name )
-{
- LPCWSTR sn, ln;
-
- if (!dir)
- return FALSE;
-
- /* the long pathname is first */
- ln = &dir->names[dir->used];
- if(ln[0])
- *long_name = ln;
- else
- return FALSE;
- dir->used += (strlenW(ln) + 1);
-
- /* followed by the short path name */
- sn = &dir->names[dir->used];
- if(sn[0])
- *short_name = sn;
- else
- *short_name = NULL;
- dir->used += (strlenW(sn) + 1);
-
- return TRUE;
-}
-
-
-/***********************************************************************
- * DOSFS_Hash
- *
- * Transform a Unix file name into a hashed DOS name. If the name is a valid
- * DOS name, it is converted to upper-case; otherwise it is replaced by a
- * hashed version that fits in 8.3 format.
- * File name can be terminated by '\0', '\\' or '/'.
- * 'buffer' must be at least 13 characters long.
- */
-static void DOSFS_Hash( LPCWSTR name, LPWSTR buffer, BOOL dir_format,
- BOOL ignore_case )
-{
- static const char invalid_chars[] = INVALID_DOS_CHARS "~.";
- static const char hash_chars[32] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
-
- LPCWSTR p, ext;
- LPWSTR dst;
- unsigned short hash;
- int i;
-
- if (dir_format)
- {
- for(i = 0; i < 11; i++) buffer[i] = ' ';
- buffer[11] = 0;
- }
-
- if (DOSFS_ValidDOSName( name, ignore_case ))
- {
- /* Check for '.' and '..' */
- if (*name == '.')
- {
- buffer[0] = '.';
- if (!dir_format) buffer[1] = buffer[2] = '\0';
- if (name[1] == '.') buffer[1] = '.';
- return;
- }
-
- /* Simply copy the name, converting to uppercase */
-
- for (dst = buffer; !IS_END_OF_NAME(*name) && (*name != '.'); name++)
- *dst++ = toupperW(*name);
- if (*name == '.')
- {
- if (dir_format) dst = buffer + 8;
- else *dst++ = '.';
- for (name++; !IS_END_OF_NAME(*name); name++)
- *dst++ = toupperW(*name);
- }
- if (!dir_format) *dst = '\0';
- return;
- }
-
- /* Compute the hash code of the file name */
- /* If you know something about hash functions, feel free to */
- /* insert a better algorithm here... */
- if (ignore_case)
- {
- for (p = name, hash = 0xbeef; !IS_END_OF_NAME(p[1]); p++)
- hash = (hash<<3) ^ (hash>>5) ^ tolowerW(*p) ^ (tolowerW(p[1]) << 8);
- hash = (hash<<3) ^ (hash>>5) ^ tolowerW(*p); /* Last character */
- }
- else
- {
- for (p = name, hash = 0xbeef; !IS_END_OF_NAME(p[1]); p++)
- hash = (hash << 3) ^ (hash >> 5) ^ *p ^ (p[1] << 8);
- hash = (hash << 3) ^ (hash >> 5) ^ *p; /* Last character */
- }
-
- /* Find last dot for start of the extension */
- for (p = name+1, ext = NULL; !IS_END_OF_NAME(*p); p++)
- if (*p == '.') ext = p;
- if (ext && IS_END_OF_NAME(ext[1]))
- ext = NULL; /* Empty extension ignored */
-
- /* Copy first 4 chars, replacing invalid chars with '_' */
- for (i = 4, p = name, dst = buffer; i > 0; i--, p++)
- {
- if (IS_END_OF_NAME(*p) || (p == ext)) break;
- *dst++ = (*p < 256 && strchr( invalid_chars, (char)*p )) ? '_' : toupperW(*p);
- }
- /* Pad to 5 chars with '~' */
- while (i-- >= 0) *dst++ = '~';
-
- /* Insert hash code converted to 3 ASCII chars */
- *dst++ = hash_chars[(hash >> 10) & 0x1f];
- *dst++ = hash_chars[(hash >> 5) & 0x1f];
- *dst++ = hash_chars[hash & 0x1f];
-
- /* Copy the first 3 chars of the extension (if any) */
- if (ext)
- {
- if (!dir_format) *dst++ = '.';
- for (i = 3, ext++; (i > 0) && !IS_END_OF_NAME(*ext); i--, ext++)
- *dst++ = (*ext < 256 && strchr( invalid_chars, (char)*ext )) ? '_' : toupperW(*ext);
- }
- if (!dir_format) *dst = '\0';
-}
-
-
-/***********************************************************************
- * DOSFS_FindUnixName
- *
- * Find the Unix file name in a given directory that corresponds to
- * a file name (either in Unix or DOS format).
- * File name can be terminated by '\0', '\\' or '/'.
- * Return TRUE if OK, FALSE if no file name matches.
- *
- * 'long_buf' must be at least 'long_len' characters long. If the long name
- * turns out to be larger than that, the function returns FALSE.
- * 'short_buf' must be at least 13 characters long.
- */
-BOOL DOSFS_FindUnixName( const DOS_FULL_NAME *path, LPCWSTR name, char *long_buf,
- INT long_len, LPWSTR short_buf, BOOL ignore_case)
-{
- DOS_DIR *dir;
- LPCWSTR long_name, short_name;
- WCHAR dos_name[12], tmp_buf[13];
- BOOL ret;
-
- LPCWSTR p = strchrW( name, '/' );
- int len = p ? (int)(p - name) : strlenW(name);
- if ((p = strchrW( name, '\\' ))) len = min( (int)(p - name), len );
- /* Ignore trailing dots and spaces */
- while (len > 1 && (name[len-1] == '.' || name[len-1] == ' ')) len--;
- if (long_len < len + 1) return FALSE;
-
- TRACE("%s,%s\n", path->long_name, debugstr_w(name) );
-
- if (!DOSFS_ToDosFCBFormat( name, dos_name )) dos_name[0] = '\0';
-
- if (!(dir = DOSFS_OpenDir( path->long_name )))
- {
- WARN("(%s,%s): can't open dir: %s\n",
- path->long_name, debugstr_w(name), strerror(errno) );
- return FALSE;
- }
-
- while ((ret = DOSFS_ReadDir( dir, &long_name, &short_name )))
- {
- /* Check against Unix name */
- if (len == strlenW(long_name))
- {
- if (!ignore_case)
- {
- if (!strncmpW( long_name, name, len )) break;
- }
- else
- {
- if (!strncmpiW( long_name, name, len )) break;
- }
- }
- if (dos_name[0])
- {
- /* Check against hashed DOS name */
- if (!short_name)
- {
- DOSFS_Hash( long_name, tmp_buf, TRUE, ignore_case );
- short_name = tmp_buf;
- }
- if (!strcmpW( dos_name, short_name )) break;
- }
- }
- if (ret)
- {
- if (long_buf) WideCharToMultiByte(CP_UNIXCP, 0, long_name, -1, long_buf, long_len, NULL, NULL);
- if (short_buf)
- {
- if (short_name)
- DOSFS_ToDosDTAFormat( short_name, short_buf );
- else
- DOSFS_Hash( long_name, short_buf, FALSE, ignore_case );
- }
- TRACE("(%s,%s) -> %s (%s)\n", path->long_name, debugstr_w(name),
- debugstr_w(long_name), short_buf ? debugstr_w(short_buf) : "***");
- }
- else
- WARN("%s not found in '%s'\n", debugstr_w(name), path->long_name);
- DOSFS_CloseDir( dir );
- return ret;
-}
-
-
-/***********************************************************************
- * DOSFS_GetPathDrive
- *
- * Get the drive specified by a given path name (DOS or Unix format).
- */
-static int DOSFS_GetPathDrive( LPCWSTR *name )
-{
- int drive;
- LPCWSTR p = *name;
-
- if (*p && (p[1] == ':'))
- {
- drive = toupperW(*p) - 'A';
- *name += 2;
- }
- else if (*p == '/') /* Absolute Unix path? */
- {
- if ((drive = DRIVE_FindDriveRootW( name )) == -1)
- {
- MESSAGE("Warning: %s not accessible from a configured DOS drive\n", debugstr_w(*name) );
- /* Assume it really was a DOS name */
- drive = DRIVE_GetCurrentDrive();
- }
- }
- else drive = DRIVE_GetCurrentDrive();
-
- if (!DRIVE_IsValid(drive))
- {
- SetLastError( ERROR_INVALID_DRIVE );
- return -1;
- }
- return drive;
-}
-
-
-/***********************************************************************
- * DOSFS_GetFullName
- *
- * Convert a file name (DOS or mixed DOS/Unix format) to a valid
- * Unix name / short DOS name pair.
- * Return FALSE if one of the path components does not exist. The last path
- * component is only checked if 'check_last' is non-zero.
- * The buffers pointed to by 'long_buf' and 'short_buf' must be
- * at least MAX_PATHNAME_LEN long.
- */
-BOOL DOSFS_GetFullName( LPCWSTR name, BOOL check_last, DOS_FULL_NAME *full )
-{
- BOOL found;
- UINT flags;
- char *p_l, *root;
- LPWSTR p_s;
- static const WCHAR driveA_rootW[] = {'A',':','\\',0};
- static const WCHAR dos_rootW[] = {'\\',0};
-
- TRACE("%s (last=%d)\n", debugstr_w(name), check_last );
-
- if ((!*name) || (*name=='\n'))
- { /* error code for Win98 */
- SetLastError(ERROR_BAD_PATHNAME);
- return FALSE;
- }
-
- if ((full->drive = DOSFS_GetPathDrive( &name )) == -1) return FALSE;
- flags = DRIVE_GetFlags( full->drive );
-
- lstrcpynA( full->long_name, DRIVE_GetRoot( full->drive ),
- sizeof(full->long_name) );
- if (full->long_name[1]) root = full->long_name + strlen(full->long_name);
- else root = full->long_name; /* root directory */
-
- strcpyW( full->short_name, driveA_rootW );
- full->short_name[0] += full->drive;
-
- if ((*name == '\\') || (*name == '/')) /* Absolute path */
- {
- while ((*name == '\\') || (*name == '/')) name++;
- }
- else /* Relative path */
- {
- lstrcpynA( root + 1, DRIVE_GetUnixCwd( full->drive ),
- sizeof(full->long_name) - (root - full->long_name) - 1 );
- if (root[1]) *root = '/';
- lstrcpynW( full->short_name + 3, DRIVE_GetDosCwd( full->drive ),
- sizeof(full->short_name)/sizeof(full->short_name[0]) - 3 );
- }
-
- p_l = full->long_name[1] ? full->long_name + strlen(full->long_name)
- : full->long_name;
- p_s = full->short_name[3] ? full->short_name + strlenW(full->short_name)
- : full->short_name + 2;
- found = TRUE;
-
- while (*name && found)
- {
- /* Check for '.' and '..' */
-
- if (*name == '.')
- {
- if (IS_END_OF_NAME(name[1]))
- {
- name++;
- while ((*name == '\\') || (*name == '/')) name++;
- continue;
- }
- else if ((name[1] == '.') && IS_END_OF_NAME(name[2]))
- {
- name += 2;
- while ((*name == '\\') || (*name == '/')) name++;
- while ((p_l > root) && (*p_l != '/')) p_l--;
- while ((p_s > full->short_name + 2) && (*p_s != '\\')) p_s--;
- *p_l = *p_s = '\0'; /* Remove trailing separator */
- continue;
- }
- }
-
- /* Make sure buffers are large enough */
-
- if ((p_s >= full->short_name + sizeof(full->short_name)/sizeof(full->short_name[0]) - 14) ||
- (p_l >= full->long_name + sizeof(full->long_name) - 1))
- {
- SetLastError( ERROR_PATH_NOT_FOUND );
- return FALSE;
- }
-
- /* Get the long and short name matching the file name */
-
- if ((found = DOSFS_FindUnixName( full, name, p_l + 1,
- sizeof(full->long_name) - (p_l - full->long_name) - 1,
- p_s + 1, !(flags & DRIVE_CASE_SENSITIVE) )))
- {
- *p_l++ = '/';
- p_l += strlen(p_l);
- *p_s++ = '\\';
- p_s += strlenW(p_s);
- while (!IS_END_OF_NAME(*name)) name++;
- }
- else if (!check_last)
- {
- *p_l++ = '/';
- *p_s++ = '\\';
- while (!IS_END_OF_NAME(*name) &&
- (p_s < full->short_name + sizeof(full->short_name)/sizeof(full->short_name[0]) - 1) &&
- (p_l < full->long_name + sizeof(full->long_name) - 1))
- {
- WCHAR wch;
- *p_s++ = tolowerW(*name);
- /* If the drive is case-sensitive we want to create new */
- /* files in lower-case otherwise we can't reopen them */
- /* under the same short name. */
- if (flags & DRIVE_CASE_SENSITIVE) wch = tolowerW(*name);
- else wch = *name;
- p_l += WideCharToMultiByte(CP_UNIXCP, 0, &wch, 1, p_l, 2, NULL, NULL);
- name++;
- }
- /* Ignore trailing dots and spaces */
- while(p_l[-1] == '.' || p_l[-1] == ' ') {
- --p_l;
- --p_s;
- }
- *p_l = '\0';
- *p_s = '\0';
- }
- while ((*name == '\\') || (*name == '/')) name++;
- }
-
- if (!found)
- {
- if (check_last)
- {
- SetLastError( ERROR_FILE_NOT_FOUND );
- return FALSE;
- }
- if (*name) /* Not last */
- {
- SetLastError( ERROR_PATH_NOT_FOUND );
- return FALSE;
- }
- }
- if (!full->long_name[0]) strcpy( full->long_name, "/" );
- if (!full->short_name[2]) strcpyW( full->short_name + 2, dos_rootW );
- TRACE("returning %s = %s\n", full->long_name, debugstr_w(full->short_name) );
- return TRUE;
-}
-
-
-/***********************************************************************
* MulDiv (KERNEL32.@)
* RETURNS
* Result of multiplication and division
diff -u -N -r -x '*~' -x '.#*' -x CVS files47/drive.c files/drive.c
--- files47/drive.c 2004-01-23 22:39:05.000000000 +0100
+++ files/drive.c 2004-01-23 22:43:07.000000000 +0100
@@ -171,6 +171,9 @@
}
+/* whether we set the =[A-Z]: environment variables when changing directories */
+static BOOL DRIVE_SetPerDriveEnv;
+
/***********************************************************************
* DRIVE_Init
*/
@@ -646,54 +649,83 @@
}
/***********************************************************************
+ * DRIVE_CheckDosCwd
+ */
+void DRIVE_CheckDosCwd(void)
+{
+ TDB *pTask = GlobalLock16(GetCurrentTask());
+ int drive = DRIVE_CurDrive;
+
+ if (!DRIVE_IsValid( 'A' + drive )) return;
+
+ /* Check if we need to change the directory to the new task. */
+ if (pTask && (pTask->curdrive & 0x80) && /* The task drive is valid */
+ ((pTask->curdrive & ~0x80) == drive) && /* and it's the one we want */
+ (DRIVE_LastTask != GetCurrentTask())) /* and the task changed */
+ {
+ static const WCHAR rootW[] = {'\\',0};
+ WCHAR curdirW[MAX_PATH];
+ MultiByteToWideChar(CP_ACP, 0, pTask->curdir, -1, curdirW, MAX_PATH);
+ /* Perform the task-switch */
+ if (!DRIVE_Chdir( drive, curdirW )) DRIVE_Chdir( drive, rootW );
+ DRIVE_LastTask = GetCurrentTask();
+ }
+}
+
+/***********************************************************************
* DRIVE_Chdir
*/
int DRIVE_Chdir( int drive, LPCWSTR path )
{
- DOS_FULL_NAME full_name;
- WCHAR buffer[MAX_PATHNAME_LEN];
- LPSTR unix_cwd;
- BY_HANDLE_FILE_INFORMATION info;
- TDB *pTask = GlobalLock16(GetCurrentTask());
+ WCHAR buffer[MAX_PATHNAME_LEN], tmp1[MAX_PATHNAME_LEN], tmp2[MAX_PATHNAME_LEN];
+ char dst[MAX_PATHNAME_LEN];
+ DWORD attr;
+ TDB* pTask = GlobalLock16(GetCurrentTask());
buffer[0] = 'A' + drive;
buffer[1] = ':';
buffer[2] = 0;
+
TRACE("(%s,%s)\n", debugstr_w(buffer), debugstr_w(path) );
+
strncpyW( buffer + 2, path, MAX_PATHNAME_LEN - 2 );
buffer[MAX_PATHNAME_LEN - 1] = 0; /* ensure 0 termination */
- if (!DOSFS_GetFullName( buffer, TRUE, &full_name )) return 0;
- if (!FILE_Stat( full_name.long_name, &info, NULL )) return 0;
- if (!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+ attr = GetFileAttributesW(buffer);
+ if (attr == INVALID_FILE_ATTRIBUTES) return 0;
+ if (!(attr & FILE_ATTRIBUTE_DIRECTORY))
{
SetLastError( ERROR_FILE_NOT_FOUND );
return 0;
}
- unix_cwd = full_name.long_name + strlen( DOSDrives[drive].root );
- while (*unix_cwd == '/') unix_cwd++;
+ GetFullPathNameW(buffer, sizeof(tmp1) / sizeof(tmp1[0]), tmp1, NULL);
+ GetShortPathNameW(tmp1, tmp2, sizeof(tmp2) / sizeof(tmp2[0]));
+ wine_get_unix_file_name(tmp2, dst, sizeof(dst));
+ if (dst[strlen(dst) - 1] == '\\')
+ dst[strlen(dst) - 1] = '\0';
+ if (tmp2[strlenW(tmp2) - 1] == '\\')
+ tmp2[strlenW(tmp2) - 1] = '\0';
TRACE("(%c:): unix_cwd=%s dos_cwd=%s\n",
- 'A' + drive, unix_cwd, debugstr_w(full_name.short_name + 3) );
+ 'A' + drive, dst, debugstr_w(tmp2 + 3) );
- HeapFree( GetProcessHeap(), 0, DOSDrives[drive].dos_cwd );
- HeapFree( GetProcessHeap(), 0, DOSDrives[drive].unix_cwd );
- DOSDrives[drive].dos_cwd = HeapAlloc(GetProcessHeap(), 0, (strlenW(full_name.short_name) - 2) * sizeof(WCHAR));
- strcpyW(DOSDrives[drive].dos_cwd, full_name.short_name + 3);
- DOSDrives[drive].unix_cwd = heap_strdup( unix_cwd );
+ if (DRIVE_SetPerDriveEnv)
+ {
+ const WCHAR envW[] = {'=', 'A' + drive, ':', 0};
+ SetEnvironmentVariableW(envW, tmp2);
+ }
if (drive == DRIVE_CurDrive)
{
UNICODE_STRING dirW;
-
- RtlInitUnicodeString( &dirW, full_name.short_name );
+ RtlInitUnicodeString( &dirW, tmp2 );
RtlSetCurrentDirectory_U( &dirW );
}
if (pTask && (pTask->curdrive & 0x80) &&
((pTask->curdrive & ~0x80) == drive))
{
- WideCharToMultiByte(CP_ACP, 0, full_name.short_name + 2, -1,
+ WideCharToMultiByte(CP_ACP, 0, tmp2 + 2, -1,
pTask->curdir, sizeof(pTask->curdir), NULL, NULL);
DRIVE_LastTask = GetCurrentTask();
}
@@ -740,17 +772,8 @@
*/
static UINT DRIVE_GetCurrentDirectory( UINT buflen, LPWSTR buf )
{
- UINT ret;
- LPCWSTR dos_cwd = DRIVE_GetDosCwd( DRIVE_GetCurrentDrive() );
- static const WCHAR driveA_rootW[] = {'A',':','\\',0};
-
- ret = strlenW(dos_cwd) + 3; /* length of WHOLE current directory */
- if (ret >= buflen) return ret + 1;
-
- strcpyW( buf, driveA_rootW );
- buf[0] += DRIVE_GetCurrentDrive();
- strcatW( buf, dos_cwd );
- return ret;
+ DRIVE_CheckDosCwd();
+ return RtlGetCurrentDirectory_U( buflen * sizeof(WCHAR), buf );
}
diff -u -N -r -x '*~' -x '.#*' -x CVS files47/file.c files/file.c
--- files47/file.c 2004-01-23 22:37:40.000000000 +0100
+++ files/file.c 2004-01-23 22:40:04.000000000 +0100
@@ -613,17 +613,16 @@
*/
DWORD WINAPI GetFileAttributesW( LPCWSTR name )
{
- DOS_FULL_NAME full_name;
- BY_HANDLE_FILE_INFORMATION info;
+ char buffer[MAX_PATH];
+ BY_HANDLE_FILE_INFORMATION info;
if (name == NULL)
{
SetLastError( ERROR_INVALID_PARAMETER );
return INVALID_FILE_ATTRIBUTES;
}
- if (!DOSFS_GetFullName( name, TRUE, &full_name) )
- return INVALID_FILE_ATTRIBUTES;
- if (!FILE_Stat( full_name.long_name, &info, NULL ))
+ if (!wine_get_unix_file_name( name, buffer, sizeof(buffer) ) ||
+ !FILE_Stat( buffer, &info, NULL ))
return INVALID_FILE_ATTRIBUTES;
return info.dwFileAttributes;
}
@@ -660,7 +659,7 @@
BOOL WINAPI SetFileAttributesW(LPCWSTR lpFileName, DWORD attributes)
{
struct stat buf;
- DOS_FULL_NAME full_name;
+ char buffer[MAX_PATH];
if (!lpFileName)
{
@@ -670,17 +669,19 @@
TRACE("(%s,%lx)\n", debugstr_w(lpFileName), attributes);
- if (!DOSFS_GetFullName( lpFileName, TRUE, &full_name ))
+ if (!wine_get_unix_file_name( lpFileName, buffer, sizeof(buffer) ))
+ {
+ SetLastError(ERROR_PATH_NOT_FOUND);
return FALSE;
-
- if(stat(full_name.long_name,&buf)==-1)
+ }
+ if (stat(buffer, &buf) == -1)
{
FILE_SetDosError();
return FALSE;
}
if (attributes & FILE_ATTRIBUTE_READONLY)
{
- if(S_ISDIR(buf.st_mode))
+ if (S_ISDIR(buf.st_mode))
/* FIXME */
WARN("FILE_ATTRIBUTE_READONLY ignored for directory.\n");
else
@@ -702,7 +703,7 @@
attributes &= ~(FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
if (attributes)
FIXME("(%s):%lx attribute(s) not implemented.\n", debugstr_w(lpFileName), attributes);
- if (-1==chmod(full_name.long_name,buf.st_mode))
+ if (-1==chmod(buffer, buf.st_mode))
{
if (GetDriveTypeW(lpFileName) == DRIVE_CDROM)
{
@@ -721,7 +722,7 @@
* to change attributes of already installed DLLs.
*/
FIXME("Couldn't set file attributes for existing file \"%s\".\n"
- "Check permissions or set VFAT \"quiet\" mount flag\n", full_name.long_name);
+ "Check permissions or set VFAT \"quiet\" mount flag\n", buffer);
}
return TRUE;
}
@@ -787,14 +788,15 @@
LPCWSTR lpFileName, /* [in] Pointer to name of file */
LPDWORD lpFileSizeHigh) /* [out] Receives high-order doubleword of size */
{
- DOS_FULL_NAME full_name;
+ char buffer[MAX_PATH];
struct stat st;
- DWORD low;
+ DWORD low;
TRACE("(%s,%p)\n",debugstr_w(lpFileName),lpFileSizeHigh);
- if (!DOSFS_GetFullName( lpFileName, TRUE, &full_name )) return INVALID_FILE_SIZE;
- if (stat(full_name.long_name, &st) != 0)
+ if (!wine_get_unix_file_name(lpFileName, buffer, sizeof(buffer)))
+ return INVALID_FILE_SIZE;
+ if (stat(buffer, &st) != 0)
{
FILE_SetDosError();
return INVALID_FILE_SIZE;
@@ -863,9 +865,9 @@
{
static const WCHAR formatW[] = {'%','x','.','t','m','p',0};
- DOS_FULL_NAME full_name;
- int i;
- LPWSTR p;
+ char tmp[MAX_PATH];
+ int i;
+ WCHAR wch, *p;
if ( !path || !prefix || !buffer )
{
@@ -911,15 +913,21 @@
}
/* Get the full path name */
-
- if (DOSFS_GetFullName( buffer, FALSE, &full_name ))
+ p = buffer + strlenW(buffer);
+ while (--p >= buffer)
{
- 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) );
+ if (*p == '/' || *p == '\\')
+ {
+ wch = *p; *p = '\0';
+ if (wine_get_unix_file_name(buffer, tmp, sizeof(tmp)))
+ {
+ if (access(tmp, W_OK) == -1 && errno == EACCES)
+ WARN("returns %s, which doesn't seem to be writeable.\n",
+ debugstr_w(buffer) );
+ }
+ *p = wch;
+ break;
+ }
}
TRACE("returning %s\n", debugstr_w(buffer) );
return unique;
@@ -933,15 +941,18 @@
*/
static HFILE FILE_DoOpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode, BOOL win32 )
{
- HFILE hFileRet;
- HANDLE handle;
- FILETIME filetime;
- WORD filedatetime[2];
- DOS_FULL_NAME full_name;
- DWORD access, sharing;
- WCHAR *p;
- WCHAR buffer[MAX_PATH];
- LPWSTR nameW;
+ HFILE hFileRet;
+ HANDLE handle;
+ FILETIME filetime;
+ WORD filedatetime[2];
+ DWORD access, sharing;
+ LPWSTR p;
+ WCHAR buffer[MAX_PATH];
+ WCHAR dst[MAX_PATH];
+ char uname[MAX_PATH];
+ LPWSTR nameW;
+ struct stat st;
+
if (!ofs) return HFILE_ERROR;
@@ -1015,8 +1026,9 @@
if ((mode & OF_SEARCH) && !(mode & OF_REOPEN))
{
/* First try the file name as is */
- if (DOSFS_GetFullName( nameW, TRUE, &full_name )) goto found;
- /* Now remove the path */
+ if (wine_get_unix_file_name(nameW, uname, sizeof(uname)) &&
+ stat(uname, &st) != -1) goto found;
+ /* Now remove the path */
if (nameW[0] && (nameW[1] == ':')) nameW += 2;
if ((p = strrchrW( nameW, '\\' ))) nameW = p + 1;
if ((p = strrchrW( nameW, '/' ))) nameW = p + 1;
@@ -1025,12 +1037,11 @@
/* Now look for the file */
- if (!DIR_SearchPath( NULL, nameW, NULL, &full_name, win32 )) goto not_found;
+ if (!DIR_SearchPath( NULL, nameW, NULL, dst, sizeof(dst)/sizeof(dst[0]), NULL, win32 )) goto not_found;
found:
- TRACE("found %s = %s\n",
- full_name.long_name, debugstr_w(full_name.short_name) );
- WideCharToMultiByte(CP_ACP, 0, full_name.short_name, -1,
+ TRACE("found %s\n", debugstr_w(dst) );
+ WideCharToMultiByte(CP_ACP, 0, dst, -1,
ofs->szPathName, sizeof(ofs->szPathName), NULL, NULL);
if (mode & OF_DELETE)
@@ -1039,7 +1050,8 @@
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, 0 );
if (!handle) goto error;
CloseHandle( handle );
- if (unlink( full_name.long_name ) == -1) goto not_found;
+ if (!wine_get_unix_file_name(nameW, uname, sizeof(uname)) ||
+ unlink( uname ) == -1) goto not_found;
TRACE("(%s): OF_DELETE return = OK\n", name);
return 1;
}
@@ -1351,8 +1363,8 @@
*/
BOOL WINAPI DeleteFileW( LPCWSTR path )
{
- DOS_FULL_NAME full_name;
- HANDLE hFile;
+ char buffer[MAX_PATH];
+ HANDLE hFile;
TRACE("%s\n", debugstr_w(path) );
if (!path || !*path)
@@ -1367,14 +1379,14 @@
return FALSE;
}
- if (!DOSFS_GetFullName( path, TRUE, &full_name )) return FALSE;
+ if (!wine_get_unix_file_name( path, buffer, sizeof(buffer) )) return FALSE;
/* check if we are allowed to delete the source */
hFile = FILE_CreateFile( path, GENERIC_READ|GENERIC_WRITE, 0,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, 0 );
if (!hFile) return FALSE;
- if (unlink( full_name.long_name ) == -1)
+ if (unlink( buffer ) == -1)
{
FILE_SetDosError();
CloseHandle(hFile);
@@ -1584,9 +1596,9 @@
*/
BOOL WINAPI MoveFileExW( LPCWSTR fn1, LPCWSTR fn2, DWORD flag )
{
- DOS_FULL_NAME full_name1, full_name2;
- HANDLE hFile;
- DWORD attr = INVALID_FILE_ATTRIBUTES;
+ char buffer1[MAX_PATH], buffer2[MAX_PATH];
+ BY_HANDLE_FILE_INFORMATION info1, info2;
+ HANDLE hFile;
TRACE("(%s,%s,%04lx)\n", debugstr_w(fn1), debugstr_w(fn2), flag);
@@ -1601,7 +1613,8 @@
/* Filename1 has to be always set to a valid path. Filename2 may be NULL
if the source file has to be deleted.
*/
- if (!fn1) {
+ if (!fn1)
+ {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
@@ -1612,34 +1625,28 @@
they are given but it can't reply with a reasonable returncode. Success
means in that case success for entering the values into the registry.
*/
- if(!DOSFS_GetFullName( fn1, TRUE, &full_name1 ))
+ if (!wine_get_unix_file_name(fn1, buffer1, sizeof(buffer1)) ||
+ !FILE_Stat(buffer1, &info1, NULL))
{
- if(!(flag & MOVEFILE_DELAY_UNTIL_REBOOT))
+ if (!(flag & MOVEFILE_DELAY_UNTIL_REBOOT))
return FALSE;
}
if (fn2) /* !fn2 means delete fn1 */
{
- if (DOSFS_GetFullName( fn2, TRUE, &full_name2 ))
+ if (wine_get_unix_file_name(fn2, buffer2, sizeof(buffer2)))
{
- if(!(flag & MOVEFILE_DELAY_UNTIL_REBOOT))
- {
+ if (FILE_Stat(buffer2, &info2, NULL) && /* file exists ? */
+ !(flag & MOVEFILE_DELAY_UNTIL_REBOOT) &&
/* target exists, check if we may overwrite */
- if (!(flag & MOVEFILE_REPLACE_EXISTING))
- {
- SetLastError( ERROR_ALREADY_EXISTS );
- return FALSE;
- }
- }
- }
- else
- {
- if (!DOSFS_GetFullName( fn2, FALSE, &full_name2 ))
+ !(flag & MOVEFILE_REPLACE_EXISTING))
{
- if(!(flag & MOVEFILE_DELAY_UNTIL_REBOOT))
- return FALSE;
+ SetLastError(ERROR_ALREADY_EXISTS);
+ return FALSE;
}
}
+ else if (!(flag & MOVEFILE_DELAY_UNTIL_REBOOT))
+ return FALSE;
/* Source name and target path are valid */
@@ -1648,8 +1655,7 @@
return FILE_AddBootRenameEntry( fn1, fn2, flag );
}
- attr = GetFileAttributesW( fn1 );
- if ( attr == INVALID_FILE_ATTRIBUTES ) return FALSE;
+ if (!FILE_Stat(buffer1, &info1, NULL)) return FALSE;
/* check if we are allowed to rename the source */
hFile = FILE_CreateFile( fn1, 0, 0,
@@ -1657,9 +1663,11 @@
FILE_ATTRIBUTE_READONLY|FILE_FLAG_BACKUP_SEMANTICS, 0 );
if (!hFile)
{
- if (GetLastError() != ERROR_ACCESS_DENIED) return FALSE;
- if ( !(attr & FILE_ATTRIBUTE_DIRECTORY) ) return FALSE;
+ if (GetLastError() != ERROR_ACCESS_DENIED ||
+ !(info1.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+ return FALSE;
/* if it's a directory we can continue */
+ /* FIXME: check that code, I wonder if it still applies... */
}
else CloseHandle(hFile);
@@ -1671,49 +1679,43 @@
if(!hFile && GetLastError() != ERROR_FILE_NOT_FOUND) return FALSE;
CloseHandle(hFile);
- if (full_name1.drive != full_name2.drive)
+ if (rename(buffer1, buffer2) == -1)
+ /* Try copy/delete unless it's a directory. */
+ /* FIXME: This does not handle the (unlikely) case that the two locations
+ are on the same Wine drive, but on different Unix file systems. */
{
- if (!(flag & MOVEFILE_COPY_ALLOWED))
+ if (errno != EXDEV)
{
- SetLastError( ERROR_NOT_SAME_DEVICE );
+ FILE_SetDosError();
return FALSE;
}
- else if ( attr & FILE_ATTRIBUTE_DIRECTORY )
+ if (info1.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
/* Strange, but that's what Windows returns */
- SetLastError ( ERROR_ACCESS_DENIED );
+ SetLastError (ERROR_ACCESS_DENIED);
return FALSE;
}
- }
- if (rename( full_name1.long_name, full_name2.long_name ) == -1)
- /* Try copy/delete unless it's a directory. */
- /* FIXME: This does not handle the (unlikely) case that the two locations
- are on the same Wine drive, but on different Unix file systems. */
- {
- if ( attr & FILE_ATTRIBUTE_DIRECTORY )
+ if (!(flag & MOVEFILE_COPY_ALLOWED))
{
- FILE_SetDosError();
+ SetLastError(ERROR_NOT_SAME_DEVICE);
return FALSE;
}
- else
- {
- if ( ! CopyFileW( fn1, fn2, !(flag & MOVEFILE_REPLACE_EXISTING) ))
- return FALSE;
- if ( ! DeleteFileW ( fn1 ) )
- return FALSE;
- }
+ if (!CopyFileW(fn1, fn2, !(flag & MOVEFILE_REPLACE_EXISTING)))
+ return FALSE;
+ if (!DeleteFileW(fn1))
+ return FALSE;
}
- if (is_executable( full_name1.long_name ) != is_executable( full_name2.long_name ))
+ if (is_executable(buffer1) != is_executable(buffer2))
{
struct stat fstat;
- if (stat( full_name2.long_name, &fstat ) != -1)
+ if (stat(buffer2, &fstat) != -1)
{
- if (is_executable( full_name2.long_name ))
+ if (is_executable(buffer2))
/* set executable bit where read bit is set */
fstat.st_mode |= (fstat.st_mode & 0444) >> 2;
else
fstat.st_mode &= ~0111;
- chmod( full_name2.long_name, fstat.st_mode );
+ chmod(buffer2, fstat.st_mode);
}
}
return TRUE;
@@ -1722,16 +1724,15 @@
{
if (flag & MOVEFILE_DELAY_UNTIL_REBOOT)
{
- if (flag & MOVEFILE_COPY_ALLOWED) {
+ if (flag & MOVEFILE_COPY_ALLOWED)
+ {
WARN("Illegal flag\n");
- SetLastError( ERROR_GEN_FAILURE );
+ SetLastError(ERROR_GEN_FAILURE);
return FALSE;
}
-
- return FILE_AddBootRenameEntry( fn1, NULL, flag );
+ return FILE_AddBootRenameEntry(fn1, NULL, flag);
}
-
- if (unlink( full_name1.long_name ) == -1)
+ if (unlink(buffer1) == -1)
{
FILE_SetDosError();
return FALSE;
@@ -1952,7 +1953,7 @@
LPCWSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
LPVOID lpFileInformation)
{
- DOS_FULL_NAME full_name;
+ char buffer[MAX_PATH];
BY_HANDLE_FILE_INFORMATION info;
if (!lpFileName || !lpFileInformation)
@@ -1961,11 +1962,16 @@
return FALSE;
}
- if (fInfoLevelId == GetFileExInfoStandard) {
+ if (fInfoLevelId == GetFileExInfoStandard)
+ {
LPWIN32_FILE_ATTRIBUTE_DATA lpFad =
(LPWIN32_FILE_ATTRIBUTE_DATA) lpFileInformation;
- if (!DOSFS_GetFullName( lpFileName, TRUE, &full_name )) return FALSE;
- if (!FILE_Stat( full_name.long_name, &info, NULL )) return FALSE;
+ if (!wine_get_unix_file_name( lpFileName, buffer, sizeof(buffer) ))
+ {
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ return FALSE;
+ }
+ if (!FILE_Stat( buffer, &info, NULL )) return FALSE;
lpFad->dwFileAttributes = info.dwFileAttributes;
lpFad->ftCreationTime = info.ftCreationTime;
@@ -1974,7 +1980,8 @@
lpFad->nFileSizeHigh = info.nFileSizeHigh;
lpFad->nFileSizeLow = info.nFileSizeLow;
}
- else {
+ else
+ {
FIXME("invalid info level %d!\n", fInfoLevelId);
return FALSE;
}
diff -u -N -r -x '*~' -x '.#*' -x CVS include47/file.h include/file.h
--- include47/file.h 2004-01-19 22:40:11.000000000 +0100
+++ include/file.h 2004-01-20 22:14:05.000000000 +0100
@@ -35,14 +35,6 @@
#define MAX_PATHNAME_LEN 1024
-/* Definition of a full DOS file name */
-typedef struct
-{
- char long_name[MAX_PATHNAME_LEN]; /* Long pathname in Unix format */
- WCHAR short_name[MAX_PATHNAME_LEN]; /* Short pathname in DOS 8.3 format */
- int drive;
-} DOS_FULL_NAME;
-
#define IS_END_OF_NAME(ch) (!(ch) || ((ch) == '/') || ((ch) == '\\'))
/* locale-independent case conversion */
@@ -70,14 +62,8 @@
extern int DIR_Init(void);
extern UINT DIR_GetWindowsUnixDir( LPSTR path, UINT count );
extern UINT DIR_GetSystemUnixDir( LPSTR path, UINT count );
-extern DWORD DIR_SearchPath( LPCWSTR path, LPCWSTR name, LPCWSTR ext,
- DOS_FULL_NAME *full_name, BOOL win32 );
/* files/dos_fs.c */
extern BOOL DOSFS_ToDosFCBFormat( LPCWSTR name, LPWSTR buffer );
-extern BOOL DOSFS_FindUnixName( const DOS_FULL_NAME *path, LPCWSTR name, char *long_buf,
- INT long_len, LPWSTR short_buf, BOOL ignore_case );
-extern BOOL DOSFS_GetFullName( LPCWSTR name, BOOL check_last,
- DOS_FULL_NAME *full );
#endif /* __WINE_FILE_H */
diff -u -N -r -x '*~' -x '.#*' -x CVS include47/winternl.h include/winternl.h
--- include47/winternl.h 2004-01-21 21:48:53.000000000 +0100
+++ include/winternl.h 2004-01-27 20:54:32.000000000 +0100
@@ -999,15 +999,6 @@
#define FILE_DEVICE_IS_MOUNTED 0x00000020
#define FILE_VIRTUAL_VOLUME 0x00000040
-/* Characteristics of a File System */
-#define FILE_REMOVABLE_MEDIA 0x00000001
-#define FILE_READ_ONLY_DEVICE 0x00000002
-#define FILE_FLOPPY_DISKETTE 0x00000004
-#define FILE_WRITE_ONE_MEDIA 0x00000008
-#define FILE_REMOTE_DEVICE 0x00000010
-#define FILE_DEVICE_IS_MOUNTED 0x00000020
-#define FILE_VIRTUAL_VOLUME 0x00000040
-
#if (_WIN32_WINNT >= 0x0501)
#define INTERNAL_TS_ACTIVE_CONSOLE_ID ( *((volatile ULONG*)(0x7ffe02d8)) )
#endif /* (_WIN32_WINNT >= 0x0501) */
More information about the wine-patches
mailing list