Convert most of the file APIs to Unicode.

This commit is contained in:
Dmitry Timoshkov 2002-08-27 01:13:58 +00:00 committed by Alexandre Julliard
parent ad0b42a099
commit d75aed2c92
21 changed files with 2874 additions and 1579 deletions

View File

@ -20,7 +20,9 @@
#include "wine/winbase16.h" #include "wine/winbase16.h"
#include "winbase.h" #include "winbase.h"
#include "winerror.h"
#include "wownt32.h" #include "wownt32.h"
#include "ntddk.h"
#include "file.h" #include "file.h"
#include "miscemu.h" #include "miscemu.h"
#include "stackframe.h" #include "stackframe.h"
@ -319,17 +321,35 @@ DWORD WINAPI LoadLibraryEx32W16( LPCSTR lpszLibFile, DWORD hFile, DWORD dwFlags
HMODULE hModule; HMODULE hModule;
DOS_FULL_NAME full_name; DOS_FULL_NAME full_name;
DWORD mutex_count; DWORD mutex_count;
UNICODE_STRING libfileW;
LPCWSTR filenameW;
static const WCHAR dllW[] = {'.','D','L','L',0};
if (!lpszLibFile)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
if (!RtlCreateUnicodeStringFromAsciiz(&libfileW, lpszLibFile))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
/* if the file can not be found, call LoadLibraryExA anyway, since it might be /* if the file can not be found, call LoadLibraryExA anyway, since it might be
a buildin module. This case is handled in MODULE_LoadLibraryExA */ a buildin module. This case is handled in MODULE_LoadLibraryExA */
if ( ! DIR_SearchPath ( NULL, lpszLibFile, ".DLL", &full_name, FALSE ) ) { filenameW = libfileW.Buffer;
strcpy ( full_name.short_name, lpszLibFile ); if ( DIR_SearchPath( NULL, filenameW, dllW, &full_name, FALSE ) )
} filenameW = full_name.short_name;
ReleaseThunkLock( &mutex_count ); ReleaseThunkLock( &mutex_count );
hModule = LoadLibraryExA( full_name.short_name, (HANDLE)hFile, dwFlags ); hModule = LoadLibraryExW( filenameW, (HANDLE)hFile, dwFlags );
RestoreThunkLock( mutex_count ); RestoreThunkLock( mutex_count );
RtlFreeUnicodeString(&libfileW);
return (DWORD)hModule; return (DWORD)hModule;
} }

View File

@ -29,6 +29,7 @@
#ifdef HAVE_SYS_ERRNO_H #ifdef HAVE_SYS_ERRNO_H
#include <sys/errno.h> #include <sys/errno.h>
#endif #endif
#include "wine/unicode.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "wine/server.h" #include "wine/server.h"
#include "ntdll_misc.h" #include "ntdll_misc.h"
@ -60,9 +61,8 @@ NTSTATUS WINAPI NtOpenFile(
ULONG ShareAccess, ULONG ShareAccess,
ULONG OpenOptions) ULONG OpenOptions)
{ {
ULONG len = 0; LPWSTR filename;
PSTR filename; static const WCHAR szDosDevices[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0};
CHAR szDosDevices[] = "\\DosDevices\\";
DOS_FULL_NAME full_name; DOS_FULL_NAME full_name;
NTSTATUS r; NTSTATUS r;
@ -79,20 +79,14 @@ NTSTATUS WINAPI NtOpenFile(
return STATUS_OBJECT_NAME_NOT_FOUND; return STATUS_OBJECT_NAME_NOT_FOUND;
} }
/* create an ascii string from the unicode filename */ filename = ObjectAttributes->ObjectName->Buffer;
RtlUnicodeToMultiByteSize( &len, ObjectAttributes->ObjectName->Buffer,
ObjectAttributes->ObjectName->Length );
filename = RtlAllocateHeap( GetProcessHeap(), 0, len + 1);
RtlUnicodeToMultiByteN(filename, len, NULL, ObjectAttributes->ObjectName->Buffer,
ObjectAttributes->ObjectName->Length );
filename[len]=0;
/* FIXME: DOSFS stuff should call here, not vice-versa */ /* FIXME: DOSFS stuff should call here, not vice-versa */
if(strncmp(filename, szDosDevices, strlen(szDosDevices))) if(strncmpW(filename, szDosDevices, strlenW(szDosDevices)))
return STATUS_OBJECT_NAME_NOT_FOUND; return STATUS_OBJECT_NAME_NOT_FOUND;
/* FIXME: this calls SetLastError() -> bad */ /* FIXME: this calls SetLastError() -> bad */
if(!DOSFS_GetFullName(&filename[strlen(szDosDevices)], TRUE, if(!DOSFS_GetFullName(&filename[strlenW(szDosDevices)], TRUE,
&full_name)) &full_name))
return STATUS_OBJECT_NAME_NOT_FOUND; return STATUS_OBJECT_NAME_NOT_FOUND;
@ -105,7 +99,7 @@ NTSTATUS WINAPI NtOpenFile(
req->sharing = ShareAccess; req->sharing = ShareAccess;
req->create = OPEN_EXISTING; req->create = OPEN_EXISTING;
req->attrs = 0; req->attrs = 0;
req->drive_type = GetDriveTypeA( full_name.short_name ); req->drive_type = GetDriveTypeW( full_name.short_name );
wine_server_add_data( req, full_name.long_name, strlen(full_name.long_name) ); wine_server_add_data( req, full_name.long_name, strlen(full_name.long_name) );
SetLastError(0); SetLastError(0);
r = wine_server_call( req ); r = wine_server_call( req );

View File

@ -32,16 +32,18 @@
#include "miscemu.h" #include "miscemu.h"
#include "msdos.h" #include "msdos.h"
#include "file.h" #include "file.h"
#include "wine/unicode.h"
#include "wine/debug.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(int21); WINE_DEFAULT_DEBUG_CHANNEL(int21);
void WINAPI DOSVM_Int21Handler_Ioctl( CONTEXT86 *context ) void WINAPI DOSVM_Int21Handler_Ioctl( CONTEXT86 *context )
{ {
static const WCHAR emmxxxx0W[] = {'E','M','M','X','X','X','X','0',0};
const DOS_DEVICE *dev = DOSFS_GetDeviceByHandle( const DOS_DEVICE *dev = DOSFS_GetDeviceByHandle(
DosFileHandleToWin32Handle(BX_reg(context)) ); DosFileHandleToWin32Handle(BX_reg(context)) );
if (dev && !strcasecmp( dev->name, "EMMXXXX0" )) { if (dev && !strcmpiW( dev->name, emmxxxx0W )) {
EMS_Ioctl_Handler(context); EMS_Ioctl_Handler(context);
return; return;
} }

View File

@ -41,6 +41,8 @@
#include "wine/winuser16.h" #include "wine/winuser16.h"
#include "winerror.h" #include "winerror.h"
#include "winreg.h" #include "winreg.h"
#include "ntddk.h"
#include "wine/unicode.h"
#include "drive.h" #include "drive.h"
#include "file.h" #include "file.h"
#include "heap.h" #include "heap.h"
@ -53,27 +55,30 @@ WINE_DECLARE_DEBUG_CHANNEL(file);
static DOS_FULL_NAME DIR_Windows; static DOS_FULL_NAME DIR_Windows;
static DOS_FULL_NAME DIR_System; static DOS_FULL_NAME DIR_System;
static const WCHAR wineW[] = {'w','i','n','e',0};
/*********************************************************************** /***********************************************************************
* DIR_GetPath * DIR_GetPath
* *
* Get a path name from the wine.ini file and make sure it is valid. * Get a path name from the wine.ini file and make sure it is valid.
*/ */
static int DIR_GetPath( const char *keyname, const char *defval, static int DIR_GetPath( LPCWSTR keyname, LPCWSTR defval, DOS_FULL_NAME *full_name,
DOS_FULL_NAME *full_name, char * longname, BOOL warn ) LPWSTR longname, INT longname_len, BOOL warn )
{ {
char path[MAX_PATHNAME_LEN]; WCHAR path[MAX_PATHNAME_LEN];
BY_HANDLE_FILE_INFORMATION info; BY_HANDLE_FILE_INFORMATION info;
const char *mess = "does not exist"; const char *mess = "does not exist";
PROFILE_GetWineIniString( "wine", keyname, defval, path, sizeof(path) ); PROFILE_GetWineIniString( wineW, keyname, defval, path, MAX_PATHNAME_LEN );
if (!DOSFS_GetFullName( path, TRUE, full_name ) || if (!DOSFS_GetFullName( path, TRUE, full_name ) ||
(!FILE_Stat( full_name->long_name, &info ) && (mess=strerror(errno)))|| (!FILE_Stat( full_name->long_name, &info ) && (mess=strerror(errno)))||
(!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (mess="not a directory")) || (!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (mess="not a directory")) ||
(!(GetLongPathNameA(full_name->short_name, longname, MAX_PATHNAME_LEN))) ) (!(GetLongPathNameW(full_name->short_name, longname, longname_len))) )
{ {
if (warn) if (warn)
MESSAGE("Invalid path '%s' for %s directory: %s\n", path, keyname, mess); MESSAGE("Invalid path %s for %s directory: %s\n",
debugstr_w(path), debugstr_w(keyname), mess);
return 0; return 0;
} }
return 1; return 1;
@ -86,10 +91,27 @@ static int DIR_GetPath( const char *keyname, const char *defval,
int DIR_Init(void) int DIR_Init(void)
{ {
char path[MAX_PATHNAME_LEN]; char path[MAX_PATHNAME_LEN];
char longpath[MAX_PATHNAME_LEN]; WCHAR longpath[MAX_PATHNAME_LEN];
DOS_FULL_NAME tmp_dir, profile_dir; DOS_FULL_NAME tmp_dir, profile_dir;
int drive; int drive;
const char *cwd; const char *cwd;
static const WCHAR windowsW[] = {'w','i','n','d','o','w','s',0};
static const WCHAR systemW[] = {'s','y','s','t','e','m',0};
static const WCHAR tempW[] = {'t','e','m','p',0};
static const WCHAR profileW[] = {'p','r','o','f','i','l','e',0};
static const WCHAR windows_dirW[] = {'c',':','\\','w','i','n','d','o','w','s',0};
static const WCHAR system_dirW[] = {'c',':','\\','w','i','n','d','o','w','s','\\','s','y','s','t','e','m',0};
static const WCHAR pathW[] = {'p','a','t','h',0};
static const WCHAR path_dirW[] = {'c',':','\\','w','i','n','d','o','w','s',';',
'c',':','\\','w','i','n','d','o','w','s','\\','s','y','s','t','e','m',0};
static const WCHAR path_capsW[] = {'P','A','T','H',0};
static const WCHAR temp_capsW[] = {'T','E','M','P',0};
static const WCHAR tmp_capsW[] = {'T','M','P',0};
static const WCHAR windirW[] = {'w','i','n','d','i','r',0};
static const WCHAR winsysdirW[] = {'w','i','n','s','y','s','d','i','r',0};
static const WCHAR userprofileW[] = {'U','S','E','R','P','R','O','F','I','L','E',0};
static const WCHAR systemrootW[] = {'S','Y','S','T','E','M','R','O','O','T',0};
static const WCHAR empty_strW[] = { 0 };
if (!getcwd( path, MAX_PATHNAME_LEN )) if (!getcwd( path, MAX_PATHNAME_LEN ))
{ {
@ -105,13 +127,17 @@ int DIR_Init(void)
} }
else else
{ {
WCHAR szdrive[3]={drive+'A',':',0};
MultiByteToWideChar(DRIVE_GetCodepage(drive), 0, cwd, -1, longpath, MAX_PATHNAME_LEN);
DRIVE_SetCurrentDrive( drive ); DRIVE_SetCurrentDrive( drive );
DRIVE_Chdir( drive, cwd ); DRIVE_Chdir( drive, longpath );
if(GetDriveTypeW(szdrive)==DRIVE_CDROM)
chdir("/"); /* change to root directory so as not to lock cdroms */
} }
if (!(DIR_GetPath( "windows", "c:\\windows", &DIR_Windows, longpath, TRUE )) || if (!(DIR_GetPath( windowsW, windows_dirW, &DIR_Windows, longpath, MAX_PATHNAME_LEN, TRUE )) ||
!(DIR_GetPath( "system", "c:\\windows\\system", &DIR_System, longpath, TRUE )) || !(DIR_GetPath( systemW, system_dirW, &DIR_System, longpath, MAX_PATHNAME_LEN, TRUE )) ||
!(DIR_GetPath( "temp", "c:\\windows", &tmp_dir, longpath, TRUE ))) !(DIR_GetPath( tempW, windows_dirW, &tmp_dir, longpath, MAX_PATHNAME_LEN, TRUE )))
{ {
PROFILE_UsageWineIni(); PROFILE_UsageWineIni();
return 0; return 0;
@ -135,9 +161,8 @@ int DIR_Init(void)
DRIVE_Chdir( drive, DIR_Windows.short_name + 2 ); DRIVE_Chdir( drive, DIR_Windows.short_name + 2 );
} }
PROFILE_GetWineIniString("wine", "path", "c:\\windows;c:\\windows\\system", PROFILE_GetWineIniString(wineW, pathW, path_dirW, longpath, MAX_PATHNAME_LEN);
path, sizeof(path) ); if (strchrW(longpath, '/'))
if (strchr(path, '/'))
{ {
MESSAGE("Fix your wine config to use DOS drive syntax in [wine] 'Path=' statement! (no '/' allowed)\n"); MESSAGE("Fix your wine config to use DOS drive syntax in [wine] 'Path=' statement! (no '/' allowed)\n");
PROFILE_UsageWineIni(); PROFILE_UsageWineIni();
@ -146,34 +171,34 @@ int DIR_Init(void)
/* Set the environment variables */ /* Set the environment variables */
SetEnvironmentVariableA( "PATH", path ); SetEnvironmentVariableW( path_capsW, longpath );
SetEnvironmentVariableA( "TEMP", tmp_dir.short_name ); SetEnvironmentVariableW( temp_capsW, tmp_dir.short_name );
SetEnvironmentVariableA( "TMP", tmp_dir.short_name ); SetEnvironmentVariableW( tmp_capsW, tmp_dir.short_name );
SetEnvironmentVariableA( "windir", DIR_Windows.short_name ); SetEnvironmentVariableW( windirW, DIR_Windows.short_name );
SetEnvironmentVariableA( "winsysdir", DIR_System.short_name ); SetEnvironmentVariableW( winsysdirW, DIR_System.short_name );
/* set COMSPEC only if it doesn't exist already */ /* set COMSPEC only if it doesn't exist already */
if (!GetEnvironmentVariableA( "COMSPEC", NULL, 0 )) if (!GetEnvironmentVariableA( "COMSPEC", NULL, 0 ))
SetEnvironmentVariableA( "COMSPEC", "c:\\command.com" ); SetEnvironmentVariableA( "COMSPEC", "c:\\command.com" );
TRACE("WindowsDir = %s (%s)\n", TRACE("WindowsDir = %s (%s)\n",
DIR_Windows.short_name, DIR_Windows.long_name ); debugstr_w(DIR_Windows.short_name), DIR_Windows.long_name );
TRACE("SystemDir = %s (%s)\n", TRACE("SystemDir = %s (%s)\n",
DIR_System.short_name, DIR_System.long_name ); debugstr_w(DIR_System.short_name), DIR_System.long_name );
TRACE("TempDir = %s (%s)\n", TRACE("TempDir = %s (%s)\n",
tmp_dir.short_name, tmp_dir.long_name ); debugstr_w(tmp_dir.short_name), tmp_dir.long_name );
TRACE("Path = %s\n", path ); TRACE("Path = %s\n", debugstr_w(longpath) );
TRACE("Cwd = %c:\\%s\n", TRACE("Cwd = %c:\\%s\n",
'A' + drive, DRIVE_GetDosCwd( drive ) ); 'A' + drive, debugstr_w(DRIVE_GetDosCwd(drive)) );
if (DIR_GetPath( "profile", "", &profile_dir, longpath, FALSE )) if (DIR_GetPath( profileW, empty_strW, &profile_dir, longpath, MAX_PATHNAME_LEN, FALSE ))
{ {
TRACE("USERPROFILE= %s\n", longpath ); TRACE("USERPROFILE= %s\n", debugstr_w(longpath) );
SetEnvironmentVariableA( "USERPROFILE", longpath ); SetEnvironmentVariableW( userprofileW, longpath );
} }
TRACE("SYSTEMROOT = %s\n", DIR_Windows.short_name ); TRACE("SYSTEMROOT = %s\n", debugstr_w(DIR_Windows.short_name) );
SetEnvironmentVariableA( "SYSTEMROOT", DIR_Windows.short_name ); SetEnvironmentVariableW( systemrootW, DIR_Windows.short_name );
return 1; return 1;
} }
@ -184,15 +209,25 @@ int DIR_Init(void)
*/ */
UINT WINAPI GetTempPathA( UINT count, LPSTR path ) UINT WINAPI GetTempPathA( UINT count, LPSTR path )
{ {
WCHAR pathW[MAX_PATH];
UINT ret; UINT ret;
if (!(ret = GetEnvironmentVariableA( "TMP", path, count )))
if (!(ret = GetEnvironmentVariableA( "TEMP", path, count ))) ret = GetTempPathW(MAX_PATH, pathW);
if (!(ret = GetCurrentDirectoryA( count, path )))
if (!ret)
return 0; return 0;
if (count && (ret < count - 1) && (path[ret-1] != '\\'))
if (ret > MAX_PATH)
{ {
path[ret++] = '\\'; SetLastError(ERROR_FILENAME_EXCED_RANGE);
path[ret] = '\0'; return 0;
}
ret = WideCharToMultiByte(CP_ACP, 0, pathW, -1, NULL, 0, NULL, NULL);
if (ret <= count)
{
WideCharToMultiByte(CP_ACP, 0, pathW, -1, path, count, NULL, NULL);
ret--; /* length without 0 */
} }
return ret; return ret;
} }
@ -205,16 +240,49 @@ UINT WINAPI GetTempPathW( UINT count, LPWSTR path )
{ {
static const WCHAR tmp[] = { 'T', 'M', 'P', 0 }; static const WCHAR tmp[] = { 'T', 'M', 'P', 0 };
static const WCHAR temp[] = { 'T', 'E', 'M', 'P', 0 }; static const WCHAR temp[] = { 'T', 'E', 'M', 'P', 0 };
WCHAR tmp_path[MAX_PATH];
UINT ret; UINT ret;
if (!(ret = GetEnvironmentVariableW( tmp, path, count )))
if (!(ret = GetEnvironmentVariableW( temp, path, count ))) TRACE("%u,%p\n", count, path);
if (!(ret = GetCurrentDirectoryW( count, path )))
if (!(ret = GetEnvironmentVariableW( tmp, tmp_path, MAX_PATH )))
if (!(ret = GetEnvironmentVariableW( temp, tmp_path, MAX_PATH )))
if (!(ret = GetCurrentDirectoryW( MAX_PATH, tmp_path )))
return 0; return 0;
if (count && (ret < count - 1) && (path[ret-1] != '\\'))
if (ret > MAX_PATH)
{ {
path[ret++] = '\\'; SetLastError(ERROR_FILENAME_EXCED_RANGE);
path[ret] = '\0'; return 0;
} }
ret = GetFullPathNameW(tmp_path, MAX_PATH, tmp_path, NULL);
if (!ret) return 0;
if (ret > MAX_PATH - 2)
{
SetLastError(ERROR_FILENAME_EXCED_RANGE);
return 0;
}
if (tmp_path[ret-1] != '\\')
{
tmp_path[ret++] = '\\';
tmp_path[ret] = '\0';
}
ret++; /* add space for terminating 0 */
if (count)
{
lstrcpynW(path, tmp_path, count);
if (count >= ret)
ret--; /* return length without 0 */
else if (count < 4)
path[0] = 0; /* avoid returning ambiguous "X:" */
}
TRACE("returning %u, %s\n", ret, debugstr_w(path));
return ret; return ret;
} }
@ -278,16 +346,16 @@ UINT16 WINAPI GetWindowsDirectory16( LPSTR path, UINT16 count )
/*********************************************************************** /***********************************************************************
* GetWindowsDirectoryA (KERNEL32.@) * GetWindowsDirectoryW (KERNEL32.@)
* *
* See comment for GetWindowsDirectoryW. * See comment for GetWindowsDirectoryA.
*/ */
UINT WINAPI GetWindowsDirectoryA( LPSTR path, UINT count ) UINT WINAPI GetWindowsDirectoryW( LPWSTR path, UINT count )
{ {
UINT len = strlen( DIR_Windows.short_name ) + 1; UINT len = strlenW( DIR_Windows.short_name ) + 1;
if (path && count >= len) if (path && count >= len)
{ {
strcpy( path, DIR_Windows.short_name ); strcpyW( path, DIR_Windows.short_name );
len--; len--;
} }
return len; return len;
@ -295,7 +363,7 @@ UINT WINAPI GetWindowsDirectoryA( LPSTR path, UINT count )
/*********************************************************************** /***********************************************************************
* GetWindowsDirectoryW (KERNEL32.@) * GetWindowsDirectoryA (KERNEL32.@)
* *
* Return value: * Return value:
* If buffer is large enough to hold full path and terminating '\0' character * If buffer is large enough to hold full path and terminating '\0' character
@ -303,12 +371,12 @@ UINT WINAPI GetWindowsDirectoryA( LPSTR path, UINT count )
* Otherwise function returns required size including '\0' character and * Otherwise function returns required size including '\0' character and
* does not touch the buffer. * does not touch the buffer.
*/ */
UINT WINAPI GetWindowsDirectoryW( LPWSTR path, UINT count ) UINT WINAPI GetWindowsDirectoryA( LPSTR path, UINT count )
{ {
UINT len = MultiByteToWideChar( CP_ACP, 0, DIR_Windows.short_name, -1, NULL, 0 ); UINT len = WideCharToMultiByte( CP_ACP, 0, DIR_Windows.short_name, -1, NULL, 0, NULL, NULL );
if (path && count >= len) if (path && count >= len)
{ {
MultiByteToWideChar( CP_ACP, 0, DIR_Windows.short_name, -1, path, count ); WideCharToMultiByte( CP_ACP, 0, DIR_Windows.short_name, -1, path, count, NULL, NULL );
len--; len--;
} }
return len; return len;
@ -343,16 +411,16 @@ UINT16 WINAPI GetSystemDirectory16( LPSTR path, UINT16 count )
/*********************************************************************** /***********************************************************************
* GetSystemDirectoryA (KERNEL32.@) * GetSystemDirectoryW (KERNEL32.@)
* *
* See comment for GetWindowsDirectoryW. * See comment for GetWindowsDirectoryA.
*/ */
UINT WINAPI GetSystemDirectoryA( LPSTR path, UINT count ) UINT WINAPI GetSystemDirectoryW( LPWSTR path, UINT count )
{ {
UINT len = strlen( DIR_System.short_name ) + 1; UINT len = strlenW( DIR_System.short_name ) + 1;
if (path && count >= len) if (path && count >= len)
{ {
strcpy( path, DIR_System.short_name ); strcpyW( path, DIR_System.short_name );
len--; len--;
} }
return len; return len;
@ -360,16 +428,16 @@ UINT WINAPI GetSystemDirectoryA( LPSTR path, UINT count )
/*********************************************************************** /***********************************************************************
* GetSystemDirectoryW (KERNEL32.@) * GetSystemDirectoryA (KERNEL32.@)
* *
* See comment for GetWindowsDirectoryW. * See comment for GetWindowsDirectoryA.
*/ */
UINT WINAPI GetSystemDirectoryW( LPWSTR path, UINT count ) UINT WINAPI GetSystemDirectoryA( LPSTR path, UINT count )
{ {
UINT len = MultiByteToWideChar( CP_ACP, 0, DIR_System.short_name, -1, NULL, 0 ); UINT len = WideCharToMultiByte( CP_ACP, 0, DIR_System.short_name, -1, NULL, 0, NULL, NULL );
if (path && count >= len) if (path && count >= len)
{ {
MultiByteToWideChar( CP_ACP, 0, DIR_System.short_name, -1, path, count ); WideCharToMultiByte( CP_ACP, 0, DIR_System.short_name, -1, path, count, NULL, NULL );
len--; len--;
} }
return len; return len;
@ -387,7 +455,7 @@ BOOL16 WINAPI CreateDirectory16( LPCSTR path, LPVOID dummy )
/*********************************************************************** /***********************************************************************
* CreateDirectoryA (KERNEL32.@) * CreateDirectoryW (KERNEL32.@)
* RETURNS: * RETURNS:
* TRUE : success * TRUE : success
* FALSE : failure * FALSE : failure
@ -396,15 +464,22 @@ BOOL16 WINAPI CreateDirectory16( LPCSTR path, LPVOID dummy )
* ERROR_ACCESS_DENIED: on permission problems * ERROR_ACCESS_DENIED: on permission problems
* ERROR_FILENAME_EXCED_RANGE: too long filename(s) * ERROR_FILENAME_EXCED_RANGE: too long filename(s)
*/ */
BOOL WINAPI CreateDirectoryA( LPCSTR path, BOOL WINAPI CreateDirectoryW( LPCWSTR path,
LPSECURITY_ATTRIBUTES lpsecattribs ) LPSECURITY_ATTRIBUTES lpsecattribs )
{ {
DOS_FULL_NAME full_name; DOS_FULL_NAME full_name;
TRACE_(file)("(%s,%p)\n", path, lpsecattribs ); if (!path || !*path)
{
SetLastError(ERROR_PATH_NOT_FOUND);
return FALSE;
}
TRACE_(file)("(%s,%p)\n", debugstr_w(path), lpsecattribs );
if (DOSFS_GetDevice( path )) if (DOSFS_GetDevice( path ))
{ {
TRACE_(file)("cannot use device '%s'!\n",path); TRACE_(file)("cannot use device %s!\n", debugstr_w(path));
SetLastError( ERROR_ACCESS_DENIED ); SetLastError( ERROR_ACCESS_DENIED );
return FALSE; return FALSE;
} }
@ -414,7 +489,14 @@ BOOL WINAPI CreateDirectoryA( LPCSTR path,
/* the FILE_SetDosError() generated error codes don't match the /* the FILE_SetDosError() generated error codes don't match the
* CreateDirectory ones for some errnos */ * CreateDirectory ones for some errnos */
switch (errno) { switch (errno) {
case EEXIST: SetLastError(ERROR_ALREADY_EXISTS); break; case EEXIST:
{
if (!strcmp(DRIVE_GetRoot(full_name.drive), full_name.long_name))
SetLastError(ERROR_ACCESS_DENIED);
else
SetLastError(ERROR_ALREADY_EXISTS);
break;
}
case ENOSPC: SetLastError(ERROR_DISK_FULL); break; case ENOSPC: SetLastError(ERROR_DISK_FULL); break;
default: FILE_SetDosError();break; default: FILE_SetDosError();break;
} }
@ -425,14 +507,27 @@ BOOL WINAPI CreateDirectoryA( LPCSTR path,
/*********************************************************************** /***********************************************************************
* CreateDirectoryW (KERNEL32.@) * CreateDirectoryA (KERNEL32.@)
*/ */
BOOL WINAPI CreateDirectoryW( LPCWSTR path, BOOL WINAPI CreateDirectoryA( LPCSTR path,
LPSECURITY_ATTRIBUTES lpsecattribs ) LPSECURITY_ATTRIBUTES lpsecattribs )
{ {
LPSTR xpath = HEAP_strdupWtoA( GetProcessHeap(), 0, path ); UNICODE_STRING pathW;
BOOL ret = CreateDirectoryA( xpath, lpsecattribs ); BOOL ret = FALSE;
HeapFree( GetProcessHeap(), 0, xpath );
if (!path || !*path)
{
SetLastError(ERROR_PATH_NOT_FOUND);
return FALSE;
}
if (RtlCreateUnicodeStringFromAsciiz(&pathW, path))
{
ret = CreateDirectoryW(pathW.Buffer, lpsecattribs);
RtlFreeUnicodeString(&pathW);
}
else
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return ret; return ret;
} }
@ -467,17 +562,23 @@ BOOL16 WINAPI RemoveDirectory16( LPCSTR path )
/*********************************************************************** /***********************************************************************
* RemoveDirectoryA (KERNEL32.@) * RemoveDirectoryW (KERNEL32.@)
*/ */
BOOL WINAPI RemoveDirectoryA( LPCSTR path ) BOOL WINAPI RemoveDirectoryW( LPCWSTR path )
{ {
DOS_FULL_NAME full_name; DOS_FULL_NAME full_name;
TRACE_(file)("'%s'\n", path ); if (!path)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
TRACE_(file)("%s\n", debugstr_w(path));
if (DOSFS_GetDevice( path )) if (DOSFS_GetDevice( path ))
{ {
TRACE_(file)("cannot remove device '%s'!\n", path); TRACE_(file)("cannot remove device %s!\n", debugstr_w(path));
SetLastError( ERROR_FILE_NOT_FOUND ); SetLastError( ERROR_FILE_NOT_FOUND );
return FALSE; return FALSE;
} }
@ -492,13 +593,26 @@ BOOL WINAPI RemoveDirectoryA( LPCSTR path )
/*********************************************************************** /***********************************************************************
* RemoveDirectoryW (KERNEL32.@) * RemoveDirectoryA (KERNEL32.@)
*/ */
BOOL WINAPI RemoveDirectoryW( LPCWSTR path ) BOOL WINAPI RemoveDirectoryA( LPCSTR path )
{ {
LPSTR xpath = HEAP_strdupWtoA( GetProcessHeap(), 0, path ); UNICODE_STRING pathW;
BOOL ret = RemoveDirectoryA( xpath ); BOOL ret = FALSE;
HeapFree( GetProcessHeap(), 0, xpath );
if (!path)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (RtlCreateUnicodeStringFromAsciiz(&pathW, path))
{
ret = RemoveDirectoryW(pathW.Buffer);
RtlFreeUnicodeString(&pathW);
}
else
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return ret; return ret;
} }
@ -508,53 +622,58 @@ BOOL WINAPI RemoveDirectoryW( LPCWSTR path )
* *
* Helper function for DIR_SearchPath. * Helper function for DIR_SearchPath.
*/ */
static BOOL DIR_TryPath( const DOS_FULL_NAME *dir, LPCSTR name, static BOOL DIR_TryPath( const DOS_FULL_NAME *dir, LPCWSTR name,
DOS_FULL_NAME *full_name ) DOS_FULL_NAME *full_name )
{ {
LPSTR p_l = full_name->long_name + strlen(dir->long_name) + 1; LPSTR p_l = full_name->long_name + strlen(dir->long_name) + 1;
LPSTR p_s = full_name->short_name + strlen(dir->short_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) - 14) || 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)) (p_l >= full_name->long_name + sizeof(full_name->long_name) - 1))
{ {
SetLastError( ERROR_PATH_NOT_FOUND ); SetLastError( ERROR_PATH_NOT_FOUND );
return FALSE; return FALSE;
} }
if (!DOSFS_FindUnixName( dir->long_name, name, p_l, if (!DOSFS_FindUnixName( dir, name, p_l,
sizeof(full_name->long_name) - (p_l - full_name->long_name), sizeof(full_name->long_name) - (p_l - full_name->long_name),
p_s, !(DRIVE_GetFlags(dir->drive) & DRIVE_CASE_SENSITIVE) )) p_s, !(DRIVE_GetFlags(dir->drive) & DRIVE_CASE_SENSITIVE) ))
return FALSE; return FALSE;
full_name->drive = dir->drive;
strcpy( full_name->long_name, dir->long_name ); strcpy( full_name->long_name, dir->long_name );
p_l[-1] = '/'; p_l[-1] = '/';
strcpy( full_name->short_name, dir->short_name ); strcpyW( full_name->short_name, dir->short_name );
p_s[-1] = '\\'; p_s[-1] = '\\';
return TRUE; return TRUE;
} }
static BOOL DIR_SearchSemicolonedPaths(LPCSTR name, DOS_FULL_NAME *full_name, LPSTR pathlist) static BOOL DIR_SearchSemicolonedPaths(LPCWSTR name, DOS_FULL_NAME *full_name, LPWSTR pathlist)
{ {
LPSTR next, buffer = NULL; LPWSTR next, buffer = NULL;
INT len = strlen(name), newlen, currlen = 0; INT len = strlenW(name), newlen, currlen = 0;
BOOL ret = FALSE; BOOL ret = FALSE;
next = pathlist; next = pathlist;
while (!ret && next) while (!ret && next)
{ {
LPSTR cur = next; static const WCHAR bkslashW[] = {'\\',0};
LPWSTR cur = next;
while (*cur == ';') cur++; while (*cur == ';') cur++;
if (!*cur) break; if (!*cur) break;
next = strchr( cur, ';' ); next = strchrW( cur, ';' );
if (next) *next++ = '\0'; if (next) *next++ = '\0';
newlen = strlen(cur) + len + 2; newlen = strlenW(cur) + len + 2;
if (newlen > currlen) if (newlen > currlen)
{ {
if (!(buffer = HeapReAlloc( GetProcessHeap(), 0, buffer, newlen))) if (!(buffer = HeapReAlloc( GetProcessHeap(), 0, buffer, newlen * sizeof(WCHAR))))
goto done; goto done;
currlen = newlen; currlen = newlen;
} }
strcpy( buffer, cur );
strcat( buffer, "\\" ); strcpyW( buffer, cur );
strcat( buffer, name ); strcatW( buffer, bkslashW );
strcatW( buffer, name );
ret = DOSFS_GetFullName( buffer, TRUE, full_name ); ret = DOSFS_GetFullName( buffer, TRUE, full_name );
} }
done: done:
@ -569,17 +688,18 @@ done:
* Helper function for DIR_SearchPath. * Helper function for DIR_SearchPath.
* Search in the specified path, or in $PATH if NULL. * Search in the specified path, or in $PATH if NULL.
*/ */
static BOOL DIR_TryEnvironmentPath( LPCSTR name, DOS_FULL_NAME *full_name, LPCSTR envpath ) static BOOL DIR_TryEnvironmentPath( LPCWSTR name, DOS_FULL_NAME *full_name, LPCWSTR envpath )
{ {
LPSTR path; LPWSTR path;
BOOL ret = FALSE; BOOL ret = FALSE;
DWORD size; DWORD size;
static const WCHAR pathW[] = {'P','A','T','H',0};
size = envpath ? strlen(envpath)+1 : GetEnvironmentVariableA( "PATH", NULL, 0 ); size = envpath ? strlenW(envpath)+1 : GetEnvironmentVariableW( pathW, NULL, 0 );
if (!size) return FALSE; if (!size) return FALSE;
if (!(path = HeapAlloc( GetProcessHeap(), 0, size ))) return FALSE; if (!(path = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) return FALSE;
if (envpath) strcpy( path, envpath ); if (envpath) strcpyW( path, envpath );
else if (!GetEnvironmentVariableA( "PATH", path, size )) goto done; else if (!GetEnvironmentVariableW( pathW, path, size )) goto done;
ret = DIR_SearchSemicolonedPaths(name, full_name, path); ret = DIR_SearchSemicolonedPaths(name, full_name, path);
@ -594,27 +714,28 @@ done:
* *
* Helper function for DIR_SearchPath. * Helper function for DIR_SearchPath.
*/ */
static BOOL DIR_TryModulePath( LPCSTR name, DOS_FULL_NAME *full_name, BOOL win32 ) static BOOL DIR_TryModulePath( LPCWSTR name, DOS_FULL_NAME *full_name, BOOL win32 )
{ {
/* FIXME: for now, GetModuleFileNameA can't return more */ /* FIXME: for now, GetModuleFileNameW can't return more */
/* than OFS_MAXPATHNAME. This may change with Win32. */ /* than OFS_MAXPATHNAME. This may change with Win32. */
WCHAR bufferW[OFS_MAXPATHNAME];
char buffer[OFS_MAXPATHNAME]; LPWSTR p;
LPSTR p;
if (!win32) if (!win32)
{ {
char buffer[OFS_MAXPATHNAME];
if (!GetCurrentTask()) return FALSE; if (!GetCurrentTask()) return FALSE;
if (!GetModuleFileName16( GetCurrentTask(), buffer, sizeof(buffer) )) if (!GetModuleFileName16( GetCurrentTask(), buffer, sizeof(buffer) ))
buffer[0]='\0'; return FALSE;
MultiByteToWideChar(CP_ACP, 0, buffer, -1, bufferW, OFS_MAXPATHNAME);
} else { } else {
if (!GetModuleFileNameA( 0, buffer, sizeof(buffer) )) if (!GetModuleFileNameW( 0, bufferW, OFS_MAXPATHNAME ) )
buffer[0]='\0'; return FALSE;
} }
if (!(p = strrchr( buffer, '\\' ))) return FALSE; if (!(p = strrchrW( bufferW, '\\' ))) return FALSE;
if (sizeof(buffer) - (++p - buffer) <= strlen(name)) return FALSE; if (OFS_MAXPATHNAME - (++p - bufferW) <= strlenW(name)) return FALSE;
strcpy( p, name ); strcpyW( p, name );
return DOSFS_GetFullName( buffer, TRUE, full_name ); return DOSFS_GetFullName( bufferW, TRUE, full_name );
} }
@ -623,32 +744,33 @@ static BOOL DIR_TryModulePath( LPCSTR name, DOS_FULL_NAME *full_name, BOOL win32
* *
* Helper function for DIR_SearchPath. * Helper function for DIR_SearchPath.
*/ */
static BOOL DIR_TryAppPath( LPCSTR name, DOS_FULL_NAME *full_name ) static BOOL DIR_TryAppPath( LPCWSTR name, DOS_FULL_NAME *full_name )
{ {
HKEY hkAppPaths = 0, hkApp = 0; HKEY hkAppPaths = 0, hkApp = 0;
char lpAppName[MAX_PATHNAME_LEN], lpAppPaths[MAX_PATHNAME_LEN]; WCHAR lpAppName[MAX_PATHNAME_LEN], lpAppPaths[MAX_PATHNAME_LEN];
LPSTR lpFileName; LPWSTR lpFileName;
BOOL res = FALSE; BOOL res = FALSE;
DWORD type, count; DWORD type, count;
static const WCHAR PathW[] = {'P','a','t','h',0};
if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths", &hkAppPaths) != ERROR_SUCCESS) if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths", &hkAppPaths) != ERROR_SUCCESS)
return FALSE; return FALSE;
if (GetModuleFileNameA(0, lpAppName, sizeof(lpAppName)) == 0) if (!GetModuleFileNameW(0, lpAppName, MAX_PATHNAME_LEN))
{ {
WARN("huh, module not found ??\n"); WARN("huh, module not found ??\n");
goto end; goto end;
} }
lpFileName = strrchr(lpAppName, '\\'); lpFileName = strrchrW(lpAppName, '\\');
if (!lpFileName) if (!lpFileName)
goto end; goto end;
else lpFileName++; /* skip '\\' */ else lpFileName++; /* skip '\\' */
if (RegOpenKeyA(hkAppPaths, lpFileName, &hkApp) != ERROR_SUCCESS) if (RegOpenKeyW(hkAppPaths, lpFileName, &hkApp) != ERROR_SUCCESS)
goto end; goto end;
count = sizeof(lpAppPaths); count = sizeof(lpAppPaths);
if (RegQueryValueExA(hkApp, "Path", 0, &type, (LPBYTE)lpAppPaths, &count) != ERROR_SUCCESS) if (RegQueryValueExW(hkApp, PathW, 0, &type, (LPBYTE)lpAppPaths, &count) != ERROR_SUCCESS)
goto end; goto end;
TRACE("successfully opened App Paths for '%s'\n", lpFileName); TRACE("successfully opened App Paths for %s\n", debugstr_w(lpFileName));
res = DIR_SearchSemicolonedPaths(name, full_name, lpAppPaths); res = DIR_SearchSemicolonedPaths(name, full_name, lpAppPaths);
end: end:
@ -667,19 +789,19 @@ end:
* *
* FIXME: should return long path names. * FIXME: should return long path names.
*/ */
DWORD DIR_SearchPath( LPCSTR path, LPCSTR name, LPCSTR ext, DWORD DIR_SearchPath( LPCWSTR path, LPCWSTR name, LPCWSTR ext,
DOS_FULL_NAME *full_name, BOOL win32 ) DOS_FULL_NAME *full_name, BOOL win32 )
{ {
LPCSTR p; LPCWSTR p;
LPSTR tmp = NULL; LPWSTR tmp = NULL;
BOOL ret = TRUE; BOOL ret = TRUE;
/* First check the supplied parameters */ /* First check the supplied parameters */
p = strrchr( name, '.' ); p = strrchrW( name, '.' );
if (p && !strchr( p, '/' ) && !strchr( p, '\\' )) if (p && !strchrW( p, '/' ) && !strchrW( p, '\\' ))
ext = NULL; /* Ignore the specified extension */ ext = NULL; /* Ignore the specified extension */
if (FILE_contains_path (name)) if (FILE_contains_pathW (name))
path = NULL; /* Ignore path if name already contains a path */ path = NULL; /* Ignore path if name already contains a path */
if (path && !*path) path = NULL; /* Ignore empty path */ if (path && !*path) path = NULL; /* Ignore empty path */
@ -687,20 +809,20 @@ DWORD DIR_SearchPath( LPCSTR path, LPCSTR name, LPCSTR ext,
if (ext) if (ext)
{ {
DWORD len = strlen(name) + strlen(ext); DWORD len = strlenW(name) + strlenW(ext);
if (!(tmp = HeapAlloc( GetProcessHeap(), 0, len + 1 ))) if (!(tmp = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) )))
{ {
SetLastError( ERROR_OUTOFMEMORY ); SetLastError( ERROR_OUTOFMEMORY );
return 0; return 0;
} }
strcpy( tmp, name ); strcpyW( tmp, name );
strcat( tmp, ext ); strcatW( tmp, ext );
name = tmp; name = tmp;
} }
/* If the name contains an explicit path, everything's easy */ /* If the name contains an explicit path, everything's easy */
if (FILE_contains_path(name)) if (FILE_contains_pathW(name))
{ {
ret = DOSFS_GetFullName( name, TRUE, full_name ); ret = DOSFS_GetFullName( name, TRUE, full_name );
goto done; goto done;
@ -751,7 +873,7 @@ done:
/*********************************************************************** /***********************************************************************
* SearchPathA [KERNEL32.@] * SearchPathW [KERNEL32.@]
* *
* Searches for a specified file in the search path. * Searches for a specified file in the search path.
* *
@ -778,10 +900,10 @@ done:
* If the file is not found, calls SetLastError(ERROR_FILE_NOT_FOUND) * If the file is not found, calls SetLastError(ERROR_FILE_NOT_FOUND)
* (tested on NT 4.0) * (tested on NT 4.0)
*/ */
DWORD WINAPI SearchPathA( LPCSTR path, LPCSTR name, LPCSTR ext, DWORD buflen, DWORD WINAPI SearchPathW( LPCWSTR path, LPCWSTR name, LPCWSTR ext, DWORD buflen,
LPSTR buffer, LPSTR *lastpart ) LPWSTR buffer, LPWSTR *lastpart )
{ {
LPSTR p, res; LPSTR res;
DOS_FULL_NAME full_name; DOS_FULL_NAME full_name;
if (!DIR_SearchPath( path, name, ext, &full_name, TRUE )) if (!DIR_SearchPath( path, name, ext, &full_name, TRUE ))
@ -789,60 +911,72 @@ DWORD WINAPI SearchPathA( LPCSTR path, LPCSTR name, LPCSTR ext, DWORD buflen,
SetLastError(ERROR_FILE_NOT_FOUND); SetLastError(ERROR_FILE_NOT_FOUND);
return 0; return 0;
} }
lstrcpynA( buffer, full_name.short_name, buflen );
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 + res = full_name.long_name +
strlen(DRIVE_GetRoot( full_name.short_name[0] - 'A' )); strlen(DRIVE_GetRoot( full_name.drive ));
while (*res == '/') res++; while (*res == '/') res++;
if (buflen) if (buflen)
{ {
if (buflen > 3) lstrcpynA( buffer + 3, res, buflen - 3 ); LPWSTR p;
for (p = buffer; *p; p++) if (*p == '/') *p = '\\'; if (buflen > 3)
if (lastpart) *lastpart = strrchr( buffer, '\\' ) + 1; {
MultiByteToWideChar(DRIVE_GetCodepage(full_name.drive), 0,
res, -1, buffer + 3, buflen - 3);
buffer[buflen - 1] = 0;
} }
TRACE("Returning %d\n", strlen(res) + 3 ); for (p = buffer; *p; p++) if (*p == '/') *p = '\\';
return strlen(res) + 3; if (lastpart) *lastpart = strrchrW( buffer, '\\' ) + 1;
}
TRACE("Returning %s\n", debugstr_w(buffer) );
return strlenW(buffer);
} }
/*********************************************************************** /***********************************************************************
* SearchPathW (KERNEL32.@) * SearchPathA (KERNEL32.@)
*/ */
DWORD WINAPI SearchPathW( LPCWSTR path, LPCWSTR name, LPCWSTR ext, DWORD WINAPI SearchPathA( LPCSTR path, LPCSTR name, LPCSTR ext,
DWORD buflen, LPWSTR buffer, LPWSTR *lastpart ) DWORD buflen, LPSTR buffer, LPSTR *lastpart )
{ {
LPWSTR p; UNICODE_STRING pathW, nameW, extW;
LPSTR res; WCHAR bufferW[MAX_PATH];
DOS_FULL_NAME full_name; DWORD ret, retW;
LPSTR pathA = HEAP_strdupWtoA( GetProcessHeap(), 0, path ); if (path) RtlCreateUnicodeStringFromAsciiz(&pathW, path);
LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name ); else pathW.Buffer = NULL;
LPSTR extA = HEAP_strdupWtoA( GetProcessHeap(), 0, ext ); if (name) RtlCreateUnicodeStringFromAsciiz(&nameW, name);
DWORD ret = DIR_SearchPath( pathA, nameA, extA, &full_name, TRUE ); else nameW.Buffer = NULL;
HeapFree( GetProcessHeap(), 0, extA ); if (ext) RtlCreateUnicodeStringFromAsciiz(&extW, ext);
HeapFree( GetProcessHeap(), 0, nameA ); else extW.Buffer = NULL;
HeapFree( GetProcessHeap(), 0, pathA );
if (!ret) return 0;
if (buflen > 0 && !MultiByteToWideChar( CP_ACP, 0, full_name.short_name, -1, buffer, buflen )) retW = SearchPathW(pathW.Buffer, nameW.Buffer, extW.Buffer, MAX_PATH, bufferW, NULL);
buffer[buflen-1] = 0;
res = full_name.long_name + if (!retW)
strlen(DRIVE_GetRoot( full_name.short_name[0] - 'A' )); ret = 0;
while (*res == '/') res++; else if (retW > MAX_PATH)
if (buflen)
{ {
if (buflen > 3) SetLastError(ERROR_FILENAME_EXCED_RANGE);
{ ret = 0;
if (!MultiByteToWideChar( CP_ACP, 0, res, -1, buffer+3, buflen-3 ))
buffer[buflen-1] = 0;
} }
for (p = buffer; *p; p++) if (*p == '/') *p = '\\'; else
if (lastpart)
{ {
for (p = *lastpart = buffer; *p; p++) ret = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL);
if (*p == '\\') *lastpart = p + 1; if (buflen >= ret)
{
WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buffer, buflen, NULL, NULL);
ret--; /* length without 0 */
if (lastpart) *lastpart = strrchr(buffer, '\\') + 1;
} }
} }
return strlen(res) + 3;
RtlFreeUnicodeString(&pathW);
RtlFreeUnicodeString(&nameW);
RtlFreeUnicodeString(&extW);
return ret;
} }
@ -852,31 +986,31 @@ DWORD WINAPI SearchPathW( LPCWSTR path, LPCWSTR name, LPCWSTR ext,
* *
* FIXME: should return long path names.? * FIXME: should return long path names.?
*/ */
static BOOL search_alternate_path(LPCSTR dll_path, LPCSTR name, LPCSTR ext, static BOOL search_alternate_path(LPCWSTR dll_path, LPCWSTR name, LPCWSTR ext,
DOS_FULL_NAME *full_name) DOS_FULL_NAME *full_name)
{ {
LPCSTR p; LPCWSTR p;
LPSTR tmp = NULL; LPWSTR tmp = NULL;
BOOL ret = TRUE; BOOL ret = TRUE;
/* First check the supplied parameters */ /* First check the supplied parameters */
p = strrchr( name, '.' ); p = strrchrW( name, '.' );
if (p && !strchr( p, '/' ) && !strchr( p, '\\' )) if (p && !strchrW( p, '/' ) && !strchrW( p, '\\' ))
ext = NULL; /* Ignore the specified extension */ ext = NULL; /* Ignore the specified extension */
/* Allocate a buffer for the file name and extension */ /* Allocate a buffer for the file name and extension */
if (ext) if (ext)
{ {
DWORD len = strlen(name) + strlen(ext); DWORD len = strlenW(name) + strlenW(ext);
if (!(tmp = HeapAlloc( GetProcessHeap(), 0, len + 1 ))) if (!(tmp = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) )))
{ {
SetLastError( ERROR_OUTOFMEMORY ); SetLastError( ERROR_OUTOFMEMORY );
return 0; return 0;
} }
strcpy( tmp, name ); strcpyW( tmp, name );
strcat( tmp, ext ); strcatW( tmp, ext );
name = tmp; name = tmp;
} }
@ -922,28 +1056,42 @@ static BOOL search_alternate_path(LPCSTR dll_path, LPCSTR name, LPCSTR ext,
* *
* NOTES * NOTES
* If the file is not found, calls SetLastError(ERROR_FILE_NOT_FOUND) * If the file is not found, calls SetLastError(ERROR_FILE_NOT_FOUND)
*
* FIXME: convert to unicode
*/ */
DWORD DIR_SearchAlternatePath( LPCSTR dll_path, LPCSTR name, LPCSTR ext, DWORD DIR_SearchAlternatePath( LPCSTR dll_path, LPCSTR name, LPCSTR ext,
DWORD buflen, LPSTR buffer, LPSTR *lastpart ) DWORD buflen, LPSTR buffer, LPSTR *lastpart )
{ {
LPSTR p, res; LPSTR p;
DOS_FULL_NAME full_name; DOS_FULL_NAME full_name;
DWORD ret = 0;
UNICODE_STRING dll_pathW, nameW, extW;
if (!search_alternate_path( dll_path, name, ext, &full_name)) if (dll_path) RtlCreateUnicodeStringFromAsciiz(&dll_pathW, dll_path);
else dll_pathW.Buffer = NULL;
if (name) RtlCreateUnicodeStringFromAsciiz(&nameW, name);
else nameW.Buffer = NULL;
if (ext) RtlCreateUnicodeStringFromAsciiz(&extW, ext);
else extW.Buffer = NULL;
if (search_alternate_path( dll_pathW.Buffer, nameW.Buffer, extW.Buffer, &full_name))
{ {
SetLastError(ERROR_FILE_NOT_FOUND); ret = WideCharToMultiByte(CP_ACP, 0, full_name.short_name, -1, NULL, 0, NULL, NULL);
return 0; if (buflen >= ret)
}
lstrcpynA( buffer, full_name.short_name, buflen );
res = full_name.long_name +
strlen(DRIVE_GetRoot( full_name.short_name[0] - 'A' ));
while (*res == '/') res++;
if (buflen)
{ {
if (buflen > 3) lstrcpynA( buffer + 3, res, buflen - 3 ); WideCharToMultiByte(CP_ACP, 0, full_name.short_name, -1, buffer, buflen, NULL, NULL);
for (p = buffer; *p; p++) if (*p == '/') *p = '\\'; for (p = buffer; *p; p++) if (*p == '/') *p = '\\';
if (lastpart) *lastpart = strrchr( buffer, '\\' ) + 1; if (lastpart) *lastpart = strrchr( buffer, '\\' ) + 1;
ret--; /* length without 0 */
} }
TRACE("Returning %d\n", strlen(res) + 3 ); }
return strlen(res) + 3; else
SetLastError(ERROR_FILE_NOT_FOUND);
RtlFreeUnicodeString(&dll_pathW);
RtlFreeUnicodeString(&nameW);
RtlFreeUnicodeString(&extW);
TRACE("Returning %ld\n", ret );
return ret;
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1392,7 +1392,7 @@ static HANDLE SMB_RegisterFile( int fd, USHORT tree_id, USHORT user_id, USHORT d
return ret; return ret;
} }
HANDLE WINAPI SMB_CreateFileA( LPCSTR uncname, DWORD access, DWORD sharing, HANDLE WINAPI SMB_CreateFileW( LPCWSTR uncname, DWORD access, DWORD sharing,
LPSECURITY_ATTRIBUTES sa, DWORD creation, LPSECURITY_ATTRIBUTES sa, DWORD creation,
DWORD attributes, HANDLE template ) DWORD attributes, HANDLE template )
{ {
@ -1400,12 +1400,14 @@ HANDLE WINAPI SMB_CreateFileA( LPCSTR uncname, DWORD access, DWORD sharing,
USHORT tree_id=0, user_id=0, dialect=0, file_id=0; USHORT tree_id=0, user_id=0, dialect=0, file_id=0;
LPSTR name,host,share,file; LPSTR name,host,share,file;
HANDLE handle = INVALID_HANDLE_VALUE; HANDLE handle = INVALID_HANDLE_VALUE;
INT len;
name = HeapAlloc(GetProcessHeap(),0,lstrlenA(uncname)); len = WideCharToMultiByte(CP_ACP, 0, uncname, -1, NULL, 0, NULL, NULL);
name = HeapAlloc(GetProcessHeap(), 0, len);
if(!name) if(!name)
return handle; return handle;
lstrcpyA(name,uncname); WideCharToMultiByte(CP_ACP, 0, uncname, -1, name, len, NULL, NULL);
if( !UNC_SplitName(name, &host, &share, &file) ) if( !UNC_SplitName(name, &host, &share, &file) )
{ {
@ -1545,21 +1547,22 @@ BOOL WINAPI SMB_ReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, LPDWORD
return r; return r;
} }
SMB_DIR* WINAPI SMB_FindFirst(LPCSTR name) SMB_DIR* WINAPI SMB_FindFirst(LPCWSTR name)
{ {
int fd = -1; int fd = -1;
LPSTR host,share,file; LPSTR host,share,file;
USHORT tree_id=0, user_id=0, dialect=0; USHORT tree_id=0, user_id=0, dialect=0;
SMB_DIR *ret = NULL; SMB_DIR *ret = NULL;
LPSTR filename; LPSTR filename;
DWORD len;
TRACE("Find %s\n",debugstr_a(name)); TRACE("Find %s\n",debugstr_w(name));
filename = HeapAlloc(GetProcessHeap(),0,lstrlenA(name)+1); len = WideCharToMultiByte( CP_ACP, 0, name, -1, NULL, 0, NULL, NULL );
filename = HeapAlloc(GetProcessHeap(),0,len);
if(!filename) if(!filename)
return ret; return ret;
WideCharToMultiByte( CP_ACP, 0, name, -1, filename, len, NULL, NULL );
lstrcpyA(filename,name);
if( !UNC_SplitName(filename, &host, &share, &file) ) if( !UNC_SplitName(filename, &host, &share, &file) )
goto done; goto done;
@ -1587,7 +1590,7 @@ done:
} }
BOOL WINAPI SMB_FindNext(SMB_DIR *dir, WIN32_FIND_DATAA *data ) BOOL WINAPI SMB_FindNext(SMB_DIR *dir, WIN32_FIND_DATAW *data )
{ {
unsigned char *ent; unsigned char *ent;
int len, fnlen; int len, fnlen;
@ -1613,14 +1616,16 @@ BOOL WINAPI SMB_FindNext(SMB_DIR *dir, WIN32_FIND_DATAA *data )
/* copy the long filename */ /* copy the long filename */
fnlen = SMB_GETDWORD(&ent[0x3c]); fnlen = SMB_GETDWORD(&ent[0x3c]);
if ( fnlen > (sizeof data->cFileName/sizeof(CHAR)) ) if ( fnlen > (sizeof data->cFileName/sizeof(WCHAR)) )
return FALSE; return FALSE;
memcpy(data->cFileName, &ent[0x5e], fnlen); MultiByteToWideChar( CP_ACP, 0, &ent[0x5e], fnlen, data->cFileName,
sizeof(data->cFileName)/sizeof(WCHAR) );
/* copy the short filename */ /* copy the short filename */
if ( ent[0x44] > (sizeof data->cAlternateFileName/sizeof(CHAR)) ) if ( ent[0x44] > (sizeof data->cAlternateFileName/sizeof(WCHAR)) )
return FALSE; return FALSE;
memcpy(data->cAlternateFileName, &ent[0x5e + len], ent[0x44]); MultiByteToWideChar( CP_ACP, 0, &ent[0x5e + len], ent[0x44], data->cAlternateFileName,
sizeof(data->cAlternateFileName)/sizeof(WCHAR) );
dir->current++; dir->current++;

View File

@ -96,7 +96,7 @@
#define TRANS2_FIND_NEXT2 0x02 #define TRANS2_FIND_NEXT2 0x02
extern BOOL WINAPI SMB_ReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, LPDWORD bytesRead, LPOVERLAPPED lpOverlapped); extern BOOL WINAPI SMB_ReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, LPDWORD bytesRead, LPOVERLAPPED lpOverlapped);
extern HANDLE WINAPI SMB_CreateFileA( LPCSTR filename, DWORD access, DWORD sharing, extern HANDLE WINAPI SMB_CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing,
LPSECURITY_ATTRIBUTES sa, DWORD creation, LPSECURITY_ATTRIBUTES sa, DWORD creation,
DWORD attributes, HANDLE template ); DWORD attributes, HANDLE template );
@ -108,8 +108,8 @@ typedef struct tagSMB_DIR
unsigned char *buffer; unsigned char *buffer;
} SMB_DIR; } SMB_DIR;
extern SMB_DIR* WINAPI SMB_FindFirst(LPCSTR filename); extern SMB_DIR* WINAPI SMB_FindFirst(LPCWSTR filename);
extern BOOL WINAPI SMB_FindNext(SMB_DIR *dir, WIN32_FIND_DATAA *data ); extern BOOL WINAPI SMB_FindNext(SMB_DIR *dir, WIN32_FIND_DATAW *data );
extern BOOL WINAPI SMB_CloseDir(SMB_DIR *dir); extern BOOL WINAPI SMB_CloseDir(SMB_DIR *dir);
#endif /* __INC_SMB__ */ #endif /* __INC_SMB__ */

View File

@ -39,15 +39,17 @@ extern int DRIVE_IsValid( int drive );
extern int DRIVE_GetCurrentDrive(void); extern int DRIVE_GetCurrentDrive(void);
extern int DRIVE_SetCurrentDrive( int drive ); extern int DRIVE_SetCurrentDrive( int drive );
extern int DRIVE_FindDriveRoot( const char **path ); extern int DRIVE_FindDriveRoot( const char **path );
extern int DRIVE_FindDriveRootW( LPCWSTR *path );
extern const char * DRIVE_GetRoot( int drive ); extern const char * DRIVE_GetRoot( int drive );
extern const char * DRIVE_GetDosCwd( int drive ); extern LPCWSTR DRIVE_GetDosCwd( int drive );
extern const char * DRIVE_GetUnixCwd( int drive ); extern const char * DRIVE_GetUnixCwd( int drive );
extern const char * DRIVE_GetDevice( int drive ); extern const char * DRIVE_GetDevice( int drive );
extern const char * DRIVE_GetLabel( int drive ); extern LPCWSTR DRIVE_GetLabel( int drive );
extern DWORD DRIVE_GetSerialNumber( int drive ); extern DWORD DRIVE_GetSerialNumber( int drive );
extern int DRIVE_SetSerialNumber( int drive, DWORD serial ); extern int DRIVE_SetSerialNumber( int drive, DWORD serial );
extern UINT DRIVE_GetFlags( int drive ); extern UINT DRIVE_GetFlags( int drive );
extern int DRIVE_Chdir( int drive, const char *path ); extern UINT DRIVE_GetCodepage( int drive );
extern int DRIVE_Chdir( int drive, LPCWSTR path );
extern int DRIVE_Disable( int drive ); extern int DRIVE_Disable( int drive );
extern int DRIVE_Enable( int drive ); extern int DRIVE_Enable( int drive );
extern int DRIVE_SetLogicalMapping ( int existing_drive, int new_drive ); extern int DRIVE_SetLogicalMapping ( int existing_drive, int new_drive );

View File

@ -26,6 +26,7 @@
#include <sys/types.h> #include <sys/types.h>
#include "winbase.h" #include "winbase.h"
#include "wine/windef16.h" /* HFILE16 */ #include "wine/windef16.h" /* HFILE16 */
#include "wine/unicode.h"
#define MAX_PATHNAME_LEN 1024 #define MAX_PATHNAME_LEN 1024
@ -33,7 +34,7 @@
typedef struct typedef struct
{ {
char long_name[MAX_PATHNAME_LEN]; /* Long pathname in Unix format */ char long_name[MAX_PATHNAME_LEN]; /* Long pathname in Unix format */
char short_name[MAX_PATHNAME_LEN]; /* Short pathname in DOS 8.3 format */ WCHAR short_name[MAX_PATHNAME_LEN]; /* Short pathname in DOS 8.3 format */
int drive; int drive;
} DOS_FULL_NAME; } DOS_FULL_NAME;
@ -42,8 +43,9 @@ typedef struct
/* DOS device descriptor */ /* DOS device descriptor */
typedef struct typedef struct
{ {
char *name; const WCHAR name[9];
int flags; int flags;
UINT codepage;
} DOS_DEVICE; } DOS_DEVICE;
/* locale-independent case conversion */ /* locale-independent case conversion */
@ -64,6 +66,12 @@ inline static int FILE_contains_path (LPCSTR name)
strchr (name, '/') || strchr (name, '\\')); strchr (name, '/') || strchr (name, '\\'));
} }
inline static int FILE_contains_pathW (LPCWSTR name)
{
return ((*name && (name[1] == ':')) ||
strchrW (name, '/') || strchrW (name, '\\'));
}
/* files/file.c */ /* files/file.c */
extern mode_t FILE_umask; extern mode_t FILE_umask;
extern int FILE_strcasecmp( const char *str1, const char *str2 ); extern int FILE_strcasecmp( const char *str1, const char *str2 );
@ -86,21 +94,20 @@ extern UINT DIR_GetWindowsUnixDir( LPSTR path, UINT count );
extern UINT DIR_GetSystemUnixDir( LPSTR path, UINT count ); extern UINT DIR_GetSystemUnixDir( LPSTR path, UINT count );
extern DWORD DIR_SearchAlternatePath( LPCSTR dll_path, LPCSTR name, LPCSTR ext, extern DWORD DIR_SearchAlternatePath( LPCSTR dll_path, LPCSTR name, LPCSTR ext,
DWORD buflen, LPSTR buffer, LPSTR *lastpart); DWORD buflen, LPSTR buffer, LPSTR *lastpart);
extern DWORD DIR_SearchPath( LPCSTR path, LPCSTR name, LPCSTR ext, extern DWORD DIR_SearchPath( LPCWSTR path, LPCWSTR name, LPCWSTR ext,
DOS_FULL_NAME *full_name, BOOL win32 ); DOS_FULL_NAME *full_name, BOOL win32 );
/* files/dos_fs.c */ /* files/dos_fs.c */
extern void DOSFS_UnixTimeToFileTime( time_t unixtime, LPFILETIME ft, extern void DOSFS_UnixTimeToFileTime( time_t unixtime, LPFILETIME ft,
DWORD remainder ); DWORD remainder );
extern time_t DOSFS_FileTimeToUnixTime( const FILETIME *ft, DWORD *remainder ); extern time_t DOSFS_FileTimeToUnixTime( const FILETIME *ft, DWORD *remainder );
extern BOOL DOSFS_ToDosFCBFormat( LPCSTR name, LPSTR buffer ); extern BOOL DOSFS_ToDosFCBFormat( LPCWSTR name, LPWSTR buffer );
extern const DOS_DEVICE *DOSFS_GetDevice( const char *name ); extern const DOS_DEVICE *DOSFS_GetDevice( LPCWSTR name );
extern const DOS_DEVICE *DOSFS_GetDeviceByHandle( HANDLE hFile ); extern const DOS_DEVICE *DOSFS_GetDeviceByHandle( HANDLE hFile );
extern HANDLE DOSFS_OpenDevice( const char *name, DWORD access, DWORD attributes, LPSECURITY_ATTRIBUTES sa); extern HANDLE DOSFS_OpenDevice( LPCWSTR name, DWORD access, DWORD attributes, LPSECURITY_ATTRIBUTES sa);
extern BOOL DOSFS_FindUnixName( LPCSTR path, LPCSTR name, LPSTR long_buf, extern BOOL DOSFS_FindUnixName( const DOS_FULL_NAME *path, LPCWSTR name, char *long_buf,
INT long_len, LPSTR short_buf, INT long_len, LPWSTR short_buf, BOOL ignore_case );
BOOL ignore_case ); extern BOOL DOSFS_GetFullName( LPCWSTR name, BOOL check_last,
extern BOOL DOSFS_GetFullName( LPCSTR name, BOOL check_last,
DOS_FULL_NAME *full ); DOS_FULL_NAME *full );
extern int DOSFS_FindNext( const char *path, const char *short_mask, extern int DOSFS_FindNext( const char *path, const char *short_mask,
const char *long_mask, int drive, BYTE attr, const char *long_mask, int drive, BYTE attr,
@ -109,12 +116,12 @@ extern int DOSFS_FindNext( const char *path, const char *short_mask,
/* profile.c */ /* profile.c */
extern int PROFILE_LoadWineIni(void); extern int PROFILE_LoadWineIni(void);
extern void PROFILE_UsageWineIni(void); extern void PROFILE_UsageWineIni(void);
extern int PROFILE_GetWineIniString( const char *section, const char *key_name, extern int PROFILE_GetWineIniString( LPCWSTR section, LPCWSTR key_name,
const char *def, char *buffer, int len ); LPCWSTR def, LPWSTR buffer, int len );
extern int PROFILE_GetWineIniBool( char const *section, char const *key_name, int def ); extern int PROFILE_GetWineIniBool( LPCWSTR section, LPCWSTR key_name, int def );
/* win32/device.c */ /* win32/device.c */
extern HANDLE DEVICE_Open( LPCSTR filename, DWORD access, LPSECURITY_ATTRIBUTES sa ); extern HANDLE DEVICE_Open( LPCWSTR filename, DWORD access, LPSECURITY_ATTRIBUTES sa );
/* ntdll/cdrom.c.c */ /* ntdll/cdrom.c.c */
extern BOOL CDROM_DeviceIoControl(DWORD clientID, HANDLE hDevice, DWORD dwIoControlCode, extern BOOL CDROM_DeviceIoControl(DWORD clientID, HANDLE hDevice, DWORD dwIoControlCode,

View File

@ -290,8 +290,9 @@ static TDB *TASK_Create( NE_MODULE *pModule, UINT16 cmdShow, TEB *teb, LPCSTR cm
pTask->teb = teb; pTask->teb = teb;
pTask->curdrive = DRIVE_GetCurrentDrive() | 0x80; pTask->curdrive = DRIVE_GetCurrentDrive() | 0x80;
strcpy( pTask->curdir, "\\" ); strcpy( pTask->curdir, "\\" );
lstrcpynA( pTask->curdir + 1, DRIVE_GetDosCwd( DRIVE_GetCurrentDrive() ), WideCharToMultiByte(CP_ACP, 0, DRIVE_GetDosCwd(DRIVE_GetCurrentDrive()), -1,
sizeof(pTask->curdir) - 1 ); pTask->curdir + 1, sizeof(pTask->curdir) - 1, NULL, NULL);
pTask->curdir[sizeof(pTask->curdir) - 1] = 0; /* ensure 0 termination */
/* Create the thunks block */ /* Create the thunks block */

View File

@ -46,11 +46,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(reg);
/* check if value type needs string conversion (Ansi<->Unicode) */ /* check if value type needs string conversion (Ansi<->Unicode) */
static inline int is_string( DWORD type ) inline static int is_string( DWORD type )
{ {
return (type == REG_SZ) || (type == REG_EXPAND_SZ) || (type == REG_MULTI_SZ); return (type == REG_SZ) || (type == REG_EXPAND_SZ) || (type == REG_MULTI_SZ);
} }
/* check if current version is NT or Win95 */
inline static int is_version_nt(void)
{
return !(GetVersion() & 0x80000000);
}
/****************************************************************************** /******************************************************************************
* RegCreateKeyExA [ADVAPI32.@] * RegCreateKeyExA [ADVAPI32.@]
@ -90,6 +95,27 @@ DWORD WINAPI RegCreateKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, LPSTR clas
} }
/******************************************************************************
* RegOpenKeyW [ADVAPI32.@]
*
* PARAMS
* hkey [I] Handle of open key
* name [I] Address of name of subkey to open
* retkey [O] Handle to open key
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*
* NOTES
* in case of failing is retkey = 0
*/
DWORD WINAPI RegOpenKeyW( HKEY hkey, LPCWSTR name, LPHKEY retkey )
{
return RegOpenKeyExW( hkey, name, 0, KEY_ALL_ACCESS, retkey );
}
/****************************************************************************** /******************************************************************************
* RegCreateKeyA [ADVAPI32.@] * RegCreateKeyA [ADVAPI32.@]
*/ */
@ -101,6 +127,43 @@ DWORD WINAPI RegCreateKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey )
/******************************************************************************
* RegOpenKeyExW [ADVAPI32.@]
*
* Opens the specified key
*
* Unlike RegCreateKeyEx, this does not create the key if it does not exist.
*
* PARAMS
* hkey [I] Handle of open key
* name [I] Name of subkey to open
* reserved [I] Reserved - must be zero
* access [I] Security access mask
* retkey [O] Handle to open key
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*
* NOTES
* in case of failing is retkey = 0
*/
DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, REGSAM access, LPHKEY retkey )
{
OBJECT_ATTRIBUTES attr;
UNICODE_STRING nameW;
attr.Length = sizeof(attr);
attr.RootDirectory = hkey;
attr.ObjectName = &nameW;
attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
RtlInitUnicodeString( &nameW, name );
return RtlNtStatusToDosError( NtOpenKey( retkey, access, &attr ) );
}
/****************************************************************************** /******************************************************************************
* RegOpenKeyExA [ADVAPI32.@] * RegOpenKeyExA [ADVAPI32.@]
*/ */
@ -228,8 +291,7 @@ DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWOR
TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0, TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
reserved, subkeys, max_subkey, values, max_value, max_data, security, modif ); reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
if (class && !class_len && !(GetVersion() & 0x80000000 /*NT*/)) if (class && !class_len && is_version_nt()) return ERROR_INVALID_PARAMETER;
return ERROR_INVALID_PARAMETER;
status = NtQueryKey( hkey, KeyFullInformation, buffer, sizeof(buffer), &total_size ); status = NtQueryKey( hkey, KeyFullInformation, buffer, sizeof(buffer), &total_size );
if (status && status != STATUS_BUFFER_OVERFLOW) goto done; if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
@ -314,6 +376,48 @@ DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name )
} }
/******************************************************************************
* RegSetValueExW [ADVAPI32.@]
*
* Sets the data and type of a value under a register key
*
* PARAMS
* hkey [I] Handle of key to set value for
* name [I] Name of value to set
* reserved [I] Reserved - must be zero
* type [I] Flag for value type
* data [I] Address of value data
* count [I] Size of value data
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*
* NOTES
* win95 does not care about count for REG_SZ and finds out the len by itself (js)
* NT does definitely care (aj)
*/
DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved,
DWORD type, CONST BYTE *data, DWORD count )
{
UNICODE_STRING nameW;
if (!is_version_nt()) /* win95 */
{
if (type == REG_SZ) count = (strlenW( (WCHAR *)data ) + 1) * sizeof(WCHAR);
}
else if (count && is_string(type))
{
LPCWSTR str = (LPCWSTR)data;
/* if user forgot to count terminating null, add it (yes NT does this) */
if (str[count / sizeof(WCHAR) - 1] && !str[count / sizeof(WCHAR)])
count += sizeof(WCHAR);
}
RtlInitUnicodeString( &nameW, name );
return RtlNtStatusToDosError( NtSetValueKey( hkey, &nameW, 0, type, data, count ) );
}
/****************************************************************************** /******************************************************************************
* RegSetValueExA [ADVAPI32.@] * RegSetValueExA [ADVAPI32.@]
@ -376,6 +480,86 @@ DWORD WINAPI RegSetValueA( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWOR
} }
/******************************************************************************
* RegQueryValueExW [ADVAPI32.@]
*
* Retrieves type and data for a specified name associated with an open key
*
* PARAMS
* hkey [I] Handle of key to query
* name [I] Name of value to query
* reserved [I] Reserved - must be NULL
* type [O] Address of buffer for value type. If NULL, the type
* is not required.
* data [O] Address of data buffer. If NULL, the actual data is
* not required.
* count [I/O] Address of data buffer size
*
* RETURNS
* ERROR_SUCCESS: Success
* ERROR_MORE_DATA: !!! if the specified buffer is not big enough to hold the data
* buffer is left untouched. The MS-documentation is wrong (js) !!!
*/
DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWORD type,
LPBYTE data, LPDWORD count )
{
NTSTATUS status;
UNICODE_STRING name_str;
DWORD total_size;
char buffer[256], *buf_ptr = buffer;
KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
static const int info_size = info->Data - (UCHAR *)info;
TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
hkey, debugstr_w(name), reserved, type, data, count, count ? *count : 0 );
if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
RtlInitUnicodeString( &name_str, name );
if (data) total_size = min( sizeof(buffer), *count + info_size );
else total_size = info_size;
status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
buffer, total_size, &total_size );
if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
if (data)
{
/* retry with a dynamically allocated buffer */
while (status == STATUS_BUFFER_OVERFLOW && total_size - info_size <= *count)
{
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
return ERROR_NOT_ENOUGH_MEMORY;
info = (KEY_VALUE_PARTIAL_INFORMATION *)buf_ptr;
status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
buf_ptr, total_size, &total_size );
}
if (!status)
{
memcpy( data, buf_ptr + info_size, total_size - info_size );
/* if the type is REG_SZ and data is not 0-terminated
* and there is enough space in the buffer NT appends a \0 */
if (total_size - info_size <= *count-sizeof(WCHAR) && is_string(info->Type))
{
WCHAR *ptr = (WCHAR *)(data + total_size - info_size);
if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
}
}
else if (status != STATUS_BUFFER_OVERFLOW) goto done;
}
else status = STATUS_SUCCESS;
if (type) *type = info->Type;
if (count) *count = total_size - info_size;
done:
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
return RtlNtStatusToDosError(status);
}
/****************************************************************************** /******************************************************************************
* RegQueryValueExA [ADVAPI32.@] * RegQueryValueExA [ADVAPI32.@]
@ -715,3 +899,56 @@ done:
SetLastError( err ); /* restore last error code */ SetLastError( err ); /* restore last error code */
return ret; return ret;
} }
/******************************************************************************
* RegUnLoadKeyA [ADVAPI32.@]
*
* PARAMS
* hkey [I] Handle of open key
* lpSubKey [I] Address of name of subkey to unload
*/
LONG WINAPI RegUnLoadKeyA( HKEY hkey, LPCSTR lpSubKey )
{
FIXME("(%x,%s): stub\n",hkey, debugstr_a(lpSubKey));
return ERROR_SUCCESS;
}
/******************************************************************************
* RegReplaceKeyA [ADVAPI32.@]
*
* PARAMS
* hkey [I] Handle of open key
* lpSubKey [I] Address of name of subkey
* lpNewFile [I] Address of filename for file with new data
* lpOldFile [I] Address of filename for backup file
*/
LONG WINAPI RegReplaceKeyA( HKEY hkey, LPCSTR lpSubKey, LPCSTR lpNewFile,
LPCSTR lpOldFile )
{
FIXME("(%x,%s,%s,%s): stub\n", hkey, debugstr_a(lpSubKey),
debugstr_a(lpNewFile),debugstr_a(lpOldFile));
return ERROR_SUCCESS;
}
/******************************************************************************
* RegFlushKey [ADVAPI32.@]
* Immediately writes key to registry.
* Only returns after data has been written to disk.
*
* FIXME: does it really wait until data is written ?
*
* PARAMS
* hkey [I] Handle of key to write
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*/
DWORD WINAPI RegFlushKey( HKEY hkey )
{
FIXME( "(%x): stub\n", hkey );
return ERROR_SUCCESS;
}

View File

@ -1050,16 +1050,21 @@ static void _init_registry_saving( HKEY hkey_users_default )
{ {
int all; int all;
int period = 0; int period = 0;
char buffer[20]; WCHAR buffer[20];
static const WCHAR registryW[] = {'r','e','g','i','s','t','r','y',0};
static const WCHAR SaveOnlyUpdatedKeysW[] = {'S','a','v','e','O','n','l','y','U','p','d','a','t','e','d','K','e','y','s',0};
static const WCHAR PeriodicSaveW[] = {'P','e','r','i','o','d','i','c','S','a','v','e',0};
static const WCHAR WritetoHomeRegistryFilesW[] = {'W','r','i','t','e','t','o','H','o','m','e','R','e','g','i','s','t','r','y','F','i','l','e','s',0};
static const WCHAR empty_strW[] = { 0 };
all = !PROFILE_GetWineIniBool("registry","SaveOnlyUpdatedKeys",1); all = !PROFILE_GetWineIniBool(registryW, SaveOnlyUpdatedKeysW, 1);
PROFILE_GetWineIniString( "registry", "PeriodicSave", "", buffer, sizeof(buffer) ); PROFILE_GetWineIniString( registryW, PeriodicSaveW, empty_strW, buffer, 20 );
if (buffer[0]) period = atoi(buffer); if (buffer[0]) period = (int)strtolW(buffer, NULL, 10);
/* set saving level (0 for saving everything, 1 for saving only modified keys) */ /* set saving level (0 for saving everything, 1 for saving only modified keys) */
_set_registry_levels(1,!all,period*1000); _set_registry_levels(1,!all,period*1000);
if (PROFILE_GetWineIniBool("registry","WritetoHomeRegistryFiles",1)) if (PROFILE_GetWineIniBool(registryW, WritetoHomeRegistryFilesW, 1))
{ {
_save_at_exit(HKEY_CURRENT_USER,"/" SAVE_LOCAL_REGBRANCH_CURRENT_USER ); _save_at_exit(HKEY_CURRENT_USER,"/" SAVE_LOCAL_REGBRANCH_CURRENT_USER );
_save_at_exit(HKEY_LOCAL_MACHINE,"/" SAVE_LOCAL_REGBRANCH_LOCAL_MACHINE); _save_at_exit(HKEY_LOCAL_MACHINE,"/" SAVE_LOCAL_REGBRANCH_LOCAL_MACHINE);
@ -1118,29 +1123,33 @@ static void _allocate_default_keys(void) {
/* return the type of native registry [Internal] */ /* return the type of native registry [Internal] */
static int _get_reg_type(void) static int _get_reg_type(void)
{ {
char windir[MAX_PATHNAME_LEN]; WCHAR windir[MAX_PATHNAME_LEN];
char tmp[MAX_PATHNAME_LEN]; WCHAR tmp[MAX_PATHNAME_LEN];
int ret = REG_WIN31; int ret = REG_WIN31;
static const WCHAR nt_reg_pathW[] = {'\\','s','y','s','t','e','m','3','2','\\','c','o','n','f','i','g','\\','s','y','s','t','e','m',0};
static const WCHAR win9x_reg_pathW[] = {'\\','s','y','s','t','e','m','.','d','a','t',0};
static const WCHAR WineW[] = {'W','i','n','e',0};
static const WCHAR ProfileW[] = {'P','r','o','f','i','l','e',0};
static const WCHAR empty_strW[] = { 0 };
GetWindowsDirectoryA(windir,MAX_PATHNAME_LEN); GetWindowsDirectoryW(windir, MAX_PATHNAME_LEN);
/* test %windir%/system32/config/system --> winnt */ /* test %windir%/system32/config/system --> winnt */
strcpy(tmp, windir); strcpyW(tmp, windir);
strncat(tmp, "\\system32\\config\\system", MAX_PATHNAME_LEN - strlen(tmp) - 1); strcatW(tmp, nt_reg_pathW);
if(GetFileAttributesA(tmp) != (DWORD)-1) { if(GetFileAttributesW(tmp) != (DWORD)-1)
ret = REG_WINNT; ret = REG_WINNT;
}
else else
{ {
/* test %windir%/system.dat --> win95 */ /* test %windir%/system.dat --> win95 */
strcpy(tmp, windir); strcpyW(tmp, windir);
strncat(tmp, "\\system.dat", MAX_PATHNAME_LEN - strlen(tmp) - 1); strcatW(tmp, win9x_reg_pathW);
if(GetFileAttributesA(tmp) != (DWORD)-1) { if(GetFileAttributesW(tmp) != (DWORD)-1)
ret = REG_WIN95; ret = REG_WIN95;
} }
}
if ((ret == REG_WINNT) && (!PROFILE_GetWineIniString( "Wine", "Profile", "", tmp, MAX_PATHNAME_LEN))) { if ((ret == REG_WINNT) && (!PROFILE_GetWineIniString( WineW, ProfileW, empty_strW, tmp, MAX_PATHNAME_LEN )))
{
MESSAGE("When you are running with a native NT directory specify\n"); MESSAGE("When you are running with a native NT directory specify\n");
MESSAGE("'Profile=<profiledirectory>' or disable loading of Windows\n"); MESSAGE("'Profile=<profiledirectory>' or disable loading of Windows\n");
MESSAGE("registry (LoadWindowsRegistryFiles=N)\n"); MESSAGE("registry (LoadWindowsRegistryFiles=N)\n");
@ -1255,7 +1264,7 @@ static LPSTR _get_tmp_fn(FILE **f)
} }
/* convert win95 native registry file to wine format [Internal] */ /* convert win95 native registry file to wine format [Internal] */
static LPSTR _convert_win95_registry_to_wine_format(LPCSTR fn,int level) static LPSTR _convert_win95_registry_to_wine_format(LPCWSTR fn, int level)
{ {
int fd; int fd;
FILE *f; FILE *f;
@ -1278,7 +1287,8 @@ static LPSTR _convert_win95_registry_to_wine_format(LPCSTR fn,int level)
/* control signature */ /* control signature */
if (*(LPDWORD)base != W95_REG_CREG_ID) { if (*(LPDWORD)base != W95_REG_CREG_ID) {
ERR("unable to load native win95 registry file %s: unknown signature.\n",fn); ERR("unable to load native win95 registry file %s: unknown signature.\n",
debugstr_w(fn));
goto error; goto error;
} }
@ -1324,7 +1334,7 @@ static LPSTR _convert_win95_registry_to_wine_format(LPCSTR fn,int level)
error: error:
if(ret == NULL) { if(ret == NULL) {
ERR("Unable to load native win95 registry file %s.\n",fn); ERR("Unable to load native win95 registry file %s.\n", debugstr_w(fn));
ERR("Please report this.\n"); ERR("Please report this.\n");
ERR("Make a backup of the file, run a good reg cleaner program and try again!\n"); ERR("Make a backup of the file, run a good reg cleaner program and try again!\n");
} }
@ -1336,7 +1346,7 @@ error1:
} }
/* convert winnt native registry file to wine format [Internal] */ /* convert winnt native registry file to wine format [Internal] */
static LPSTR _convert_winnt_registry_to_wine_format(LPCSTR fn,int level) static LPSTR _convert_winnt_registry_to_wine_format(LPCWSTR fn, int level)
{ {
FILE *f; FILE *f;
void *base; void *base;
@ -1349,11 +1359,11 @@ static LPSTR _convert_winnt_registry_to_wine_format(LPCSTR fn,int level)
nt_hbin_sub *hbin_sub; nt_hbin_sub *hbin_sub;
nt_nk *nk; nt_nk *nk;
TRACE("%s\n", fn); TRACE("%s\n", debugstr_w(fn));
hFile = CreateFileA( fn, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); hFile = CreateFileW( fn, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
if ( hFile == INVALID_HANDLE_VALUE ) return NULL; if ( hFile == INVALID_HANDLE_VALUE ) return NULL;
hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY|SEC_COMMIT, 0, 0, NULL ); hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY|SEC_COMMIT, 0, 0, NULL );
if (!hMapping) goto error1; if (!hMapping) goto error1;
base = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 ); base = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
CloseHandle( hMapping ); CloseHandle( hMapping );
@ -1361,7 +1371,8 @@ static LPSTR _convert_winnt_registry_to_wine_format(LPCSTR fn,int level)
/* control signature */ /* control signature */
if (*(LPDWORD)base != NT_REG_HEADER_BLOCK_ID) { if (*(LPDWORD)base != NT_REG_HEADER_BLOCK_ID) {
ERR("unable to load native winnt registry file %s: unknown signature.\n",fn); ERR("unable to load native winnt registry file %s: unknown signature.\n",
debugstr_w(fn));
goto error; goto error;
} }
@ -1402,7 +1413,7 @@ error1:
} }
/* convert native registry to wine format and load it via server call [Internal] */ /* convert native registry to wine format and load it via server call [Internal] */
static void _convert_and_load_native_registry(LPCSTR fn,HKEY hkey,int reg_type,int level) static void _convert_and_load_native_registry(LPCWSTR fn, HKEY hkey, int reg_type, int level)
{ {
LPSTR tmp = NULL; LPSTR tmp = NULL;
@ -1424,10 +1435,11 @@ static void _convert_and_load_native_registry(LPCSTR fn,HKEY hkey,int reg_type,i
if (tmp != NULL) { if (tmp != NULL) {
load_wine_registry(hkey,tmp); load_wine_registry(hkey,tmp);
TRACE("File %s successfully converted to %s and loaded to registry.\n",fn,tmp); TRACE("File %s successfully converted to %s and loaded to registry.\n",
debugstr_w(fn), tmp);
unlink(tmp); unlink(tmp);
} }
else WARN("Unable to convert %s (doesn't exist?)\n",fn); else WARN("Unable to convert %s (doesn't exist?)\n", debugstr_w(fn));
free(tmp); free(tmp);
} }
@ -1435,26 +1447,35 @@ static void _convert_and_load_native_registry(LPCSTR fn,HKEY hkey,int reg_type,i
static void _load_windows_registry( HKEY hkey_users_default ) static void _load_windows_registry( HKEY hkey_users_default )
{ {
int reg_type; int reg_type;
char windir[MAX_PATHNAME_LEN]; WCHAR windir[MAX_PATHNAME_LEN];
char path[MAX_PATHNAME_LEN]; WCHAR path[MAX_PATHNAME_LEN];
static const WCHAR WineW[] = {'W','i','n','e',0};
static const WCHAR ProfileW[] = {'P','r','o','f','i','l','e',0};
static const WCHAR empty_strW[] = { 0 };
GetWindowsDirectoryA(windir,MAX_PATHNAME_LEN); GetWindowsDirectoryW(windir, MAX_PATHNAME_LEN);
reg_type = _get_reg_type(); reg_type = _get_reg_type();
switch (reg_type) { switch (reg_type) {
case REG_WINNT: { case REG_WINNT: {
HKEY hkey; HKEY hkey;
static const WCHAR ntuser_datW[] = {'\\','n','t','u','s','e','r','.','d','a','t',0};
static const WCHAR defaultW[] = {'\\','s','y','s','t','e','m','3','2','\\','c','o','n','f','i','g','\\','d','e','f','a','u','l','t',0};
static const WCHAR systemW[] = {'\\','s','y','s','t','e','m','3','2','\\','c','o','n','f','i','g','\\','s','y','s','t','e','m',0};
static const WCHAR softwareW[] = {'\\','s','y','s','t','e','m','3','2','\\','c','o','n','f','i','g','\\','s','o','f','t','w','a','r','e',0};
static const WCHAR samW[] = {'\\','s','y','s','t','e','m','3','2','\\','c','o','n','f','i','g','\\','s','a','m',0};
static const WCHAR securityW[] = {'\\','s','y','s','t','e','m','3','2','\\','c','o','n','f','i','g','\\','s','e','c','u','r','i','t','y',0};
/* user specific ntuser.dat */ /* user specific ntuser.dat */
if (PROFILE_GetWineIniString( "Wine", "Profile", "", path, MAX_PATHNAME_LEN)) { if (PROFILE_GetWineIniString( WineW, ProfileW, empty_strW, path, MAX_PATHNAME_LEN )) {
strcat(path,"\\ntuser.dat"); strcatW(path, ntuser_datW);
_convert_and_load_native_registry(path,HKEY_CURRENT_USER,REG_WINNT,1); _convert_and_load_native_registry(path,HKEY_CURRENT_USER,REG_WINNT,1);
} }
/* default user.dat */ /* default user.dat */
if (hkey_users_default) { if (hkey_users_default) {
strcpy(path,windir); strcpyW(path, windir);
strcat(path,"\\system32\\config\\default"); strcatW(path, defaultW);
_convert_and_load_native_registry(path,hkey_users_default,REG_WINNT,1); _convert_and_load_native_registry(path,hkey_users_default,REG_WINNT,1);
} }
@ -1464,25 +1485,25 @@ static void _load_windows_registry( HKEY hkey_users_default )
*/ */
if (!RegCreateKeyA(HKEY_LOCAL_MACHINE, "SYSTEM", &hkey)) { if (!RegCreateKeyA(HKEY_LOCAL_MACHINE, "SYSTEM", &hkey)) {
strcpy(path,windir); strcpyW(path, windir);
strcat(path,"\\system32\\config\\system"); strcatW(path, systemW);
_convert_and_load_native_registry(path,hkey,REG_WINNT,1); _convert_and_load_native_registry(path,hkey,REG_WINNT,1);
RegCloseKey(hkey); RegCloseKey(hkey);
} }
if (!RegCreateKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE", &hkey)) { if (!RegCreateKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE", &hkey)) {
strcpy(path,windir); strcpyW(path, windir);
strcat(path,"\\system32\\config\\software"); strcatW(path, softwareW);
_convert_and_load_native_registry(path,hkey,REG_WINNT,1); _convert_and_load_native_registry(path,hkey,REG_WINNT,1);
RegCloseKey(hkey); RegCloseKey(hkey);
} }
strcpy(path,windir); strcpyW(path, windir);
strcat(path,"\\system32\\config\\sam"); strcatW(path, samW);
_convert_and_load_native_registry(path,HKEY_LOCAL_MACHINE,REG_WINNT,0); _convert_and_load_native_registry(path,HKEY_LOCAL_MACHINE,REG_WINNT,0);
strcpy(path,windir); strcpyW(path,windir);
strcat(path,"\\system32\\config\\security"); strcatW(path, securityW);
_convert_and_load_native_registry(path,HKEY_LOCAL_MACHINE,REG_WINNT,0); _convert_and_load_native_registry(path,HKEY_LOCAL_MACHINE,REG_WINNT,0);
/* this key is generated when the nt-core booted successfully */ /* this key is generated when the nt-core booted successfully */
@ -1491,33 +1512,40 @@ static void _load_windows_registry( HKEY hkey_users_default )
} }
case REG_WIN95: case REG_WIN95:
_convert_and_load_native_registry("c:\\system.1st",HKEY_LOCAL_MACHINE,REG_WIN95,0); {
static const WCHAR system_1stW[] = {'c',':','\\','s','y','s','t','e','m','.','1','s','t',0};
static const WCHAR system_datW[] = {'\\','s','y','s','t','e','m','.','d','a','t',0};
static const WCHAR classes_datW[] = {'\\','c','l','a','s','s','e','s','.','d','a','t',0};
static const WCHAR user_datW[] = {'\\','u','s','e','r','.','d','a','t',0};
strcpy(path,windir); _convert_and_load_native_registry(system_1stW,HKEY_LOCAL_MACHINE,REG_WIN95,0);
strcat(path,"\\system.dat");
strcpyW(path, windir);
strcatW(path, system_datW);
_convert_and_load_native_registry(path,HKEY_LOCAL_MACHINE,REG_WIN95,0); _convert_and_load_native_registry(path,HKEY_LOCAL_MACHINE,REG_WIN95,0);
strcpy(path,windir); strcpyW(path, windir);
strcat(path,"\\classes.dat"); strcatW(path, classes_datW);
_convert_and_load_native_registry(path,HKEY_CLASSES_ROOT,REG_WIN95,0); _convert_and_load_native_registry(path,HKEY_CLASSES_ROOT,REG_WIN95,0);
if (PROFILE_GetWineIniString("Wine","Profile","",path,MAX_PATHNAME_LEN)) { if (PROFILE_GetWineIniString(WineW, ProfileW, empty_strW, path, MAX_PATHNAME_LEN)) {
/* user specific user.dat */ /* user specific user.dat */
strncat(path, "\\user.dat", MAX_PATHNAME_LEN - strlen(path) - 1); strcatW(path, user_datW);
_convert_and_load_native_registry(path,HKEY_CURRENT_USER,REG_WIN95,1); _convert_and_load_native_registry(path,HKEY_CURRENT_USER,REG_WIN95,1);
/* default user.dat */ /* default user.dat */
if (hkey_users_default) { if (hkey_users_default) {
strcpy(path,windir); strcpyW(path, windir);
strcat(path,"\\user.dat"); strcatW(path, user_datW);
_convert_and_load_native_registry(path,hkey_users_default,REG_WIN95,1); _convert_and_load_native_registry(path,hkey_users_default,REG_WIN95,1);
} }
} else { } else {
strcpy(path,windir); strcpyW(path, windir);
strcat(path,"\\user.dat"); strcatW(path, user_datW);
_convert_and_load_native_registry(path,HKEY_CURRENT_USER,REG_WIN95,1); _convert_and_load_native_registry(path,HKEY_CURRENT_USER,REG_WIN95,1);
} }
break; break;
}
case REG_WIN31: case REG_WIN31:
/* FIXME: here we should convert to *.reg file supported by server and call REQ_LOAD_REGISTRY, see REG_WIN95 case */ /* FIXME: here we should convert to *.reg file supported by server and call REQ_LOAD_REGISTRY, see REG_WIN95 case */
@ -1572,6 +1600,10 @@ static void _load_home_registry( HKEY hkey_users_default )
void SHELL_LoadRegistry( void ) void SHELL_LoadRegistry( void )
{ {
HKEY hkey_users_default; HKEY hkey_users_default;
static const WCHAR RegistryW[] = {'R','e','g','i','s','t','r','y',0};
static const WCHAR load_win_reg_filesW[] = {'L','o','a','d','W','i','n','d','o','w','s','R','e','g','i','s','t','r','y','F','i','l','e','s',0};
static const WCHAR load_global_reg_filesW[] = {'L','o','a','d','G','l','o','b','a','l','R','e','g','i','s','t','r','y','F','i','l','e','s',0};
static const WCHAR load_home_reg_filesW[] = {'L','o','a','d','H','o','m','e','R','e','g','i','s','t','r','y','F','i','l','e','s',0};
TRACE("(void)\n"); TRACE("(void)\n");
@ -1585,70 +1617,21 @@ void SHELL_LoadRegistry( void )
_allocate_default_keys(); _allocate_default_keys();
_set_registry_levels(0,0,0); _set_registry_levels(0,0,0);
if (PROFILE_GetWineIniBool("Registry","LoadWindowsRegistryFiles",1)) if (PROFILE_GetWineIniBool(RegistryW, load_win_reg_filesW, 1))
_load_windows_registry( hkey_users_default ); _load_windows_registry( hkey_users_default );
if (PROFILE_GetWineIniBool("Registry","LoadGlobalRegistryFiles",1)) if (PROFILE_GetWineIniBool(RegistryW, load_global_reg_filesW, 1))
_load_global_registry(); _load_global_registry();
_set_registry_levels(1,0,0); _set_registry_levels(1,0,0);
if (PROFILE_GetWineIniBool("Registry","LoadHomeRegistryFiles",1)) if (PROFILE_GetWineIniBool(RegistryW, load_home_reg_filesW, 1))
_load_home_registry( hkey_users_default ); _load_home_registry( hkey_users_default );
_init_registry_saving( hkey_users_default ); _init_registry_saving( hkey_users_default );
RegCloseKey(hkey_users_default); RegCloseKey(hkey_users_default);
} }
/***************************************************************************/ /***************************************************************************/
/* API FUNCTIONS */ /* 16-BIT API FUNCTIONS */
/***************************************************************************/ /***************************************************************************/
/******************************************************************************
* RegFlushKey [ADVAPI32.@]
* Immediately writes key to registry.
* Only returns after data has been written to disk.
*
* FIXME: does it really wait until data is written ?
*
* PARAMS
* hkey [I] Handle of key to write
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*/
DWORD WINAPI RegFlushKey( HKEY hkey )
{
FIXME( "(%x): stub\n", hkey );
return ERROR_SUCCESS;
}
/******************************************************************************
* RegUnLoadKeyA [ADVAPI32.@]
*/
LONG WINAPI RegUnLoadKeyA( HKEY hkey, LPCSTR lpSubKey )
{
FIXME("(%x,%s): stub\n",hkey, debugstr_a(lpSubKey));
return ERROR_SUCCESS;
}
/******************************************************************************
* RegReplaceKeyA [ADVAPI32.@]
*/
LONG WINAPI RegReplaceKeyA( HKEY hkey, LPCSTR lpSubKey, LPCSTR lpNewFile,
LPCSTR lpOldFile )
{
FIXME("(%x,%s,%s,%s): stub\n", hkey, debugstr_a(lpSubKey),
debugstr_a(lpNewFile),debugstr_a(lpOldFile));
return ERROR_SUCCESS;
}
/* 16-bit functions */
/* 0 and 1 are valid rootkeys in win16 shell.dll and are used by /* 0 and 1 are valid rootkeys in win16 shell.dll and are used by
* some programs. Do not remove those cases. -MM * some programs. Do not remove those cases. -MM
*/ */

View File

@ -435,17 +435,19 @@ static void DOSCONF_Parse(char *menuname)
int DOSCONF_ReadConfig(void) int DOSCONF_ReadConfig(void)
{ {
char buffer[256]; WCHAR filename[MAX_PATH];
DOS_FULL_NAME fullname; DOS_FULL_NAME fullname;
char *filename, *menuname; WCHAR *p;
int ret = 1; int ret = 1;
static const WCHAR wineW[] = {'w','i','n','e',0};
static const WCHAR config_sysW[] = {'c','o','n','f','i','g','.','s','y','s',0};
static const WCHAR empty_strW[] = { 0 };
PROFILE_GetWineIniString( "wine", "config.sys", "", buffer, sizeof(buffer) ); PROFILE_GetWineIniString( wineW, config_sysW, empty_strW, filename, MAX_PATH );
if (!(filename = strtok(buffer, ","))) return ret; if ((p = strchrW(filename, ','))) *p = 0;
menuname = strtok(NULL, ","); if (!filename[0]) return ret;
DOSFS_GetFullName(filename, FALSE, &fullname); DOSFS_GetFullName(filename, FALSE, &fullname);
if (menuname) menu_default = strdup(menuname);
if ((cfg_fd = fopen(fullname.long_name, "r"))) if ((cfg_fd = fopen(fullname.long_name, "r")))
{ {
DOSCONF_Parse(NULL); DOSCONF_Parse(NULL);
@ -453,10 +455,9 @@ int DOSCONF_ReadConfig(void)
} }
else else
{ {
MESSAGE("Couldn't open config.sys file given as \"%s\" in" \ MESSAGE("Couldn't open config.sys file given as %s in" \
" wine.conf or .winerc, section [wine] !\n", filename); " wine.conf or .winerc, section [wine] !\n", debugstr_w(filename));
ret = 0; ret = 0;
} }
if (menu_default) free(menu_default);
return ret; return ret;
} }

View File

@ -28,6 +28,7 @@
#include "miscemu.h" #include "miscemu.h"
#include "msdos.h" #include "msdos.h"
#include "file.h" #include "file.h"
#include "wine/unicode.h"
#include "wine/debug.h" #include "wine/debug.h"
/********************************************************************** /**********************************************************************
@ -74,16 +75,21 @@ void WINAPI INT_Int11Handler( CONTEXT86 *context )
for (x=0; x < 9; x++) for (x=0; x < 9; x++)
{ {
char temp[16],name[16]; WCHAR temp[16];
WCHAR comW[] = {'C','O','M','?',0};
WCHAR lptW[] = {'L','P','T','?',0};
static const WCHAR serialportsW[] = {'s','e','r','i','a','l','p','o','r','t','s',0};
static const WCHAR parallelportsW[] = {'p','a','r','a','l','l','e','l','p','o','r','t','s',0};
static const WCHAR asteriskW[] = {'*',0};
sprintf(name,"COM%d",x+1); comW[3] = '0' + x;
PROFILE_GetWineIniString("serialports",name,"*",temp,sizeof temp); PROFILE_GetWineIniString(serialportsW, comW, asteriskW, temp, 16);
if(strcmp(temp,"*")) if(strcmpW(temp, asteriskW))
serialports++; serialports++;
sprintf(name,"LPT%d",x+1); lptW[3] = '0' + x;
PROFILE_GetWineIniString("parallelports",name,"*",temp,sizeof temp); PROFILE_GetWineIniString(parallelportsW, lptW, asteriskW, temp, 16);
if(strcmp(temp,"*")) if(strcmpW(temp, asteriskW))
parallelports++; parallelports++;
} }
if (serialports > 7) /* 3 bits -- maximum value = 7 */ if (serialports > 7) /* 3 bits -- maximum value = 7 */

View File

@ -57,6 +57,7 @@
#include "msdos.h" #include "msdos.h"
#include "miscemu.h" #include "miscemu.h"
#include "task.h" #include "task.h"
#include "wine/unicode.h"
#include "wine/debug.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(int21); WINE_DEFAULT_DEBUG_CHANNEL(int21);
@ -428,30 +429,37 @@ static void INT21_ParseFileNameIntoFCB( CONTEXT86 *context )
CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Esi ); CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Esi );
char *fcb = char *fcb =
CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edi ); CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edi );
char *buffer, *s, *d; char *s;
WCHAR *buffer;
WCHAR fcbW[12];
INT buffer_len, len;
AL_reg(context) = 0xff; /* failed */ AL_reg(context) = 0xff; /* failed */
TRACE("filename: '%s'\n", filename); TRACE("filename: '%s'\n", filename);
buffer = HeapAlloc( GetProcessHeap(), 0, strlen(filename) + 1);
s = filename; s = filename;
d = buffer; len = 0;
while (*s) while (*s)
{ {
if ((*s != ' ') && (*s != '\r') && (*s != '\n')) if ((*s != ' ') && (*s != '\r') && (*s != '\n'))
*d++ = *s++; {
s++;
len++;
}
else else
break; break;
} }
*d = '\0'; buffer_len = MultiByteToWideChar(CP_OEMCP, 0, filename, len, NULL, 0);
DOSFS_ToDosFCBFormat(buffer, fcb + 1); buffer = HeapAlloc( GetProcessHeap(), 0, (buffer_len + 1) * sizeof(WCHAR));
*fcb = 0; len = MultiByteToWideChar(CP_OEMCP, 0, filename, len, buffer, buffer_len);
TRACE("FCB: '%s'\n", ((CHAR *)fcb + 1)); buffer[len] = 0;
DOSFS_ToDosFCBFormat(buffer, fcbW);
HeapFree(GetProcessHeap(), 0, buffer); HeapFree(GetProcessHeap(), 0, buffer);
WideCharToMultiByte(CP_OEMCP, 0, fcbW, 12, fcb + 1, 12, NULL, NULL);
*fcb = 0;
TRACE("FCB: '%s'\n", fcb + 1);
AL_reg(context) = AL_reg(context) =
((strchr(filename, '*')) || (strchr(filename, '$'))) != 0; ((strchr(filename, '*')) || (strchr(filename, '$'))) != 0;
@ -618,6 +626,7 @@ static BOOL INT21_ChangeDir( CONTEXT86 *context )
{ {
int drive; int drive;
char *dirname = CTX_SEG_OFF_TO_LIN(context, context->SegDs,context->Edx); char *dirname = CTX_SEG_OFF_TO_LIN(context, context->SegDs,context->Edx);
WCHAR dirnameW[MAX_PATH];
TRACE("changedir %s\n", dirname); TRACE("changedir %s\n", dirname);
if (dirname[0] && (dirname[1] == ':')) if (dirname[0] && (dirname[1] == ':'))
@ -626,7 +635,8 @@ static BOOL INT21_ChangeDir( CONTEXT86 *context )
dirname += 2; dirname += 2;
} }
else drive = DRIVE_GetCurrentDrive(); else drive = DRIVE_GetCurrentDrive();
return DRIVE_Chdir( drive, dirname ); MultiByteToWideChar(CP_OEMCP, 0, dirname, -1, dirnameW, MAX_PATH);
return DRIVE_Chdir( drive, dirnameW );
} }
@ -636,10 +646,14 @@ static int INT21_FindFirst( CONTEXT86 *context )
const char *path; const char *path;
DOS_FULL_NAME full_name; DOS_FULL_NAME full_name;
FINDFILE_DTA *dta = (FINDFILE_DTA *)GetCurrentDTA(context); FINDFILE_DTA *dta = (FINDFILE_DTA *)GetCurrentDTA(context);
WCHAR pathW[MAX_PATH];
WCHAR maskW[12];
path = (const char *)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx); path = (const char *)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
MultiByteToWideChar(CP_OEMCP, 0, path, -1, pathW, MAX_PATH);
dta->unixPath = NULL; dta->unixPath = NULL;
if (!DOSFS_GetFullName( path, FALSE, &full_name )) if (!DOSFS_GetFullName( pathW, FALSE, &full_name ))
{ {
AX_reg(context) = GetLastError(); AX_reg(context) = GetLastError();
SET_CFLAG(context); SET_CFLAG(context);
@ -650,10 +664,12 @@ static int INT21_FindFirst( CONTEXT86 *context )
p = strrchr( dta->unixPath, '/' ); p = strrchr( dta->unixPath, '/' );
*p = '\0'; *p = '\0';
MultiByteToWideChar(CP_OEMCP, 0, p + 1, -1, pathW, MAX_PATH);
/* Note: terminating NULL in dta->mask overwrites dta->search_attr /* Note: terminating NULL in dta->mask overwrites dta->search_attr
* (doesn't matter as it is set below anyway) * (doesn't matter as it is set below anyway)
*/ */
if (!DOSFS_ToDosFCBFormat( p + 1, dta->mask )) if (!DOSFS_ToDosFCBFormat( pathW, maskW ))
{ {
HeapFree( GetProcessHeap(), 0, dta->unixPath ); HeapFree( GetProcessHeap(), 0, dta->unixPath );
dta->unixPath = NULL; dta->unixPath = NULL;
@ -662,6 +678,7 @@ static int INT21_FindFirst( CONTEXT86 *context )
SET_CFLAG(context); SET_CFLAG(context);
return 0; return 0;
} }
WideCharToMultiByte(CP_OEMCP, 0, maskW, 12, dta->mask, sizeof(dta->mask), NULL, NULL);
dta->drive = (path[0] && (path[1] == ':')) ? toupper(path[0]) - 'A' dta->drive = (path[0] && (path[1] == ':')) ? toupper(path[0]) - 'A'
: DRIVE_GetCurrentDrive(); : DRIVE_GetCurrentDrive();
dta->count = 0; dta->count = 0;
@ -743,7 +760,8 @@ static BOOL INT21_GetCurrentDirectory( CONTEXT86 *context )
SetLastError( ERROR_INVALID_DRIVE ); SetLastError( ERROR_INVALID_DRIVE );
return FALSE; return FALSE;
} }
lstrcpynA( ptr, DRIVE_GetDosCwd(drive), 64 ); WideCharToMultiByte(CP_OEMCP, 0, DRIVE_GetDosCwd(drive), -1, ptr, 64, NULL, NULL);
ptr[63] = 0; /* ensure 0 termination */
AX_reg(context) = 0x0100; /* success return code */ AX_reg(context) = 0x0100; /* success return code */
return TRUE; return TRUE;
} }
@ -1586,8 +1604,9 @@ void WINAPI DOS3Call( CONTEXT86 *context )
break; break;
case 0x02:{ case 0x02:{
const DOS_DEVICE *dev; const DOS_DEVICE *dev;
static const WCHAR scsimgrW[] = {'S','C','S','I','M','G','R','$',0};
if ((dev = DOSFS_GetDeviceByHandle( DosFileHandleToWin32Handle(BX_reg(context)) )) && if ((dev = DOSFS_GetDeviceByHandle( DosFileHandleToWin32Handle(BX_reg(context)) )) &&
!strcasecmp( dev->name, "SCSIMGR$" )) !strcmpiW( dev->name, scsimgrW ))
{ {
ASPI_DOS_HandleInt(context); ASPI_DOS_HandleInt(context);
} }

View File

@ -36,6 +36,7 @@
# include <unistd.h> # include <unistd.h>
#endif #endif
#include "windef.h" #include "windef.h"
#include "winnls.h"
#include "callback.h" #include "callback.h"
#include "file.h" #include "file.h"
#include "miscemu.h" #include "miscemu.h"
@ -249,17 +250,22 @@ static inline void outl( DWORD value, WORD port )
static void IO_port_init(void) static void IO_port_init(void)
{ {
char temp[1024]; char temp[1024];
WCHAR tempW[1024];
static const WCHAR portsW[] = {'p','o','r','t','s',0};
static const WCHAR readW[] = {'r','e','a','d',0};
static const WCHAR writeW[] = {'w','r','i','t','e',0};
static const WCHAR asteriskW[] = {'*',0};
do_direct_port_access = 0; do_direct_port_access = 0;
/* Can we do that? */ /* Can we do that? */
if (!iopl(3)) { if (!iopl(3)) {
iopl(0); iopl(0);
PROFILE_GetWineIniString( "ports", "read", "*", PROFILE_GetWineIniString( portsW, readW, asteriskW, tempW, 1024 );
temp, sizeof(temp) ); WideCharToMultiByte(CP_ACP, 0, tempW, -1, temp, 1024, NULL, NULL);
do_IO_port_init_read_or_write(temp, IO_READ); do_IO_port_init_read_or_write(temp, IO_READ);
PROFILE_GetWineIniString( "ports", "write", "*", PROFILE_GetWineIniString( portsW, writeW, asteriskW, tempW, 1024 );
temp, sizeof(temp) ); WideCharToMultiByte(CP_ACP, 0, tempW, -1, temp, 1024, NULL, NULL);
do_IO_port_init_read_or_write(temp, IO_WRITE); do_IO_port_init_read_or_write(temp, IO_WRITE);
} }
IO_FixCMOSCheckSum(); IO_FixCMOSCheckSum();

View File

@ -650,9 +650,12 @@ void PROCESS_InitWine( int argc, char *argv[], LPSTR win16_exe_name, HANDLE *win
{ {
DOS_FULL_NAME full_name; DOS_FULL_NAME full_name;
const char *name = main_exe_name; const char *name = main_exe_name;
UNICODE_STRING nameW;
TRACE( "starting Winelib app %s\n", debugstr_a(main_exe_name) ); TRACE( "starting Winelib app %s\n", debugstr_a(main_exe_name) );
if (DOSFS_GetFullName( name, TRUE, &full_name )) name = full_name.long_name; RtlCreateUnicodeStringFromAsciiz(&nameW, name);
if (DOSFS_GetFullName( nameW.Buffer, TRUE, &full_name )) name = full_name.long_name;
RtlFreeUnicodeString(&nameW);
CloseHandle( main_exe_file ); CloseHandle( main_exe_file );
main_exe_file = 0; main_exe_file = 0;
if (wine_dlopen( name, RTLD_NOW, error, sizeof(error) )) if (wine_dlopen( name, RTLD_NOW, error, sizeof(error) ))
@ -1194,13 +1197,16 @@ BOOL WINAPI CreateProcessA( LPCSTR app_name, LPSTR cmd_line, LPSECURITY_ATTRIBUT
if (cur_dir) if (cur_dir)
{ {
if (DOSFS_GetFullName( cur_dir, TRUE, &full_dir )) UNICODE_STRING cur_dirW;
RtlCreateUnicodeStringFromAsciiz(&cur_dirW, cur_dir);
if (DOSFS_GetFullName( cur_dirW.Buffer, TRUE, &full_dir ))
unixdir = full_dir.long_name; unixdir = full_dir.long_name;
RtlFreeUnicodeString(&cur_dirW);
} }
else else
{ {
char buf[MAX_PATH]; WCHAR buf[MAX_PATH];
if (GetCurrentDirectoryA(sizeof(buf),buf)) if (GetCurrentDirectoryW(MAX_PATH, buf))
{ {
if (DOSFS_GetFullName( buf, TRUE, &full_dir )) unixdir = full_dir.long_name; if (DOSFS_GetFullName( buf, TRUE, &full_dir )) unixdir = full_dir.long_name;
} }
@ -1253,11 +1259,16 @@ BOOL WINAPI CreateProcessA( LPCSTR app_name, LPSTR cmd_line, LPSECURITY_ATTRIBUT
/* fall through */ /* fall through */
case BINARY_UNIX_EXE: case BINARY_UNIX_EXE:
{ {
/* unknown file, try as unix executable */
UNICODE_STRING nameW;
DOS_FULL_NAME full_name; DOS_FULL_NAME full_name;
const char *unixfilename = name; const char *unixfilename = name;
TRACE( "starting %s as Unix binary\n", debugstr_a(name) ); TRACE( "starting %s as Unix binary\n", debugstr_a(name) );
if (DOSFS_GetFullName( name, TRUE, &full_name )) unixfilename = full_name.long_name;
RtlCreateUnicodeStringFromAsciiz(&nameW, name);
if (DOSFS_GetFullName( nameW.Buffer, TRUE, &full_name )) unixfilename = full_name.long_name;
RtlFreeUnicodeString(&nameW);
retv = (fork_and_exec( unixfilename, tidy_cmdline, env, unixdir ) != -1); retv = (fork_and_exec( unixfilename, tidy_cmdline, env, unixdir ) != -1);
} }
break; break;

View File

@ -344,9 +344,16 @@ LPCSTR VMM_Service_Name[N_VMM_SERVICE] =
HANDLE DEVICE_Open( LPCSTR filename, DWORD access, LPSECURITY_ATTRIBUTES sa ) HANDLE DEVICE_Open( LPCWSTR filenameW, DWORD access, LPSECURITY_ATTRIBUTES sa )
{ {
const struct VxDInfo *info; const struct VxDInfo *info;
char filename[MAX_PATH];
if (!WideCharToMultiByte(CP_ACP, 0, filenameW, -1, filename, MAX_PATH, NULL, NULL))
{
SetLastError( ERROR_FILE_NOT_FOUND );
return 0;
}
for (info = VxDList; info->name; info++) for (info = VxDList; info->name; info++)
if (!strncasecmp( info->name, filename, strlen(info->name) )) if (!strncasecmp( info->name, filename, strlen(info->name) ))
@ -1563,4 +1570,3 @@ static BOOL DeviceIo_HASP(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInB
return retv; return retv;
} }