Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
d75aed2c
Commit
d75aed2c
authored
Aug 27, 2002
by
Dmitry Timoshkov
Committed by
Alexandre Julliard
Aug 27, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Convert most of the file APIs to Unicode.
parent
ad0b42a0
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
2858 additions
and
1563 deletions
+2858
-1563
wowthunk.c
dlls/kernel/wowthunk.c
+24
-4
file.c
dlls/ntdll/file.c
+7
-13
int21.c
dlls/winedos/int21.c
+3
-1
directory.c
files/directory.c
+347
-199
dos_fs.c
files/dos_fs.c
+710
-431
drive.c
files/drive.c
+393
-198
file.c
files/file.c
+445
-239
profile.c
files/profile.c
+458
-291
smb.c
files/smb.c
+18
-13
smb.h
files/smb.h
+3
-3
drive.h
include/drive.h
+5
-3
file.h
include/file.h
+21
-14
task.c
loader/task.c
+3
-2
registry.c
memory/registry.c
+240
-3
registry.c
misc/registry.c
+90
-107
dosconf.c
msdos/dosconf.c
+10
-9
int11.c
msdos/int11.c
+13
-7
int21.c
msdos/int21.c
+34
-15
ioports.c
msdos/ioports.c
+10
-4
process.c
scheduler/process.c
+16
-5
device.c
win32/device.c
+8
-2
No files found.
dlls/kernel/wowthunk.c
View file @
d75aed2c
...
...
@@ -20,7 +20,9 @@
#include "wine/winbase16.h"
#include "winbase.h"
#include "winerror.h"
#include "wownt32.h"
#include "ntddk.h"
#include "file.h"
#include "miscemu.h"
#include "stackframe.h"
...
...
@@ -319,17 +321,35 @@ DWORD WINAPI LoadLibraryEx32W16( LPCSTR lpszLibFile, DWORD hFile, DWORD dwFlags
HMODULE
hModule
;
DOS_FULL_NAME
full_name
;
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
a buildin module. This case is handled in MODULE_LoadLibraryExA */
if
(
!
DIR_SearchPath
(
NULL
,
lpszLibFile
,
".DLL"
,
&
full_name
,
FALSE
)
)
{
strcpy
(
full_name
.
short_name
,
lpszLibFile
);
}
filenameW
=
libfileW
.
Buffer
;
if
(
DIR_SearchPath
(
NULL
,
filenameW
,
dllW
,
&
full_name
,
FALSE
)
)
filenameW
=
full_name
.
short_name
;
ReleaseThunkLock
(
&
mutex_count
);
hModule
=
LoadLibraryEx
A
(
full_name
.
short_name
,
(
HANDLE
)
hFile
,
dwFlags
);
hModule
=
LoadLibraryEx
W
(
filenameW
,
(
HANDLE
)
hFile
,
dwFlags
);
RestoreThunkLock
(
mutex_count
);
RtlFreeUnicodeString
(
&
libfileW
);
return
(
DWORD
)
hModule
;
}
...
...
dlls/ntdll/file.c
View file @
d75aed2c
...
...
@@ -29,6 +29,7 @@
#ifdef HAVE_SYS_ERRNO_H
#include <sys/errno.h>
#endif
#include "wine/unicode.h"
#include "wine/debug.h"
#include "wine/server.h"
#include "ntdll_misc.h"
...
...
@@ -60,9 +61,8 @@ NTSTATUS WINAPI NtOpenFile(
ULONG
ShareAccess
,
ULONG
OpenOptions
)
{
ULONG
len
=
0
;
PSTR
filename
;
CHAR
szDosDevices
[]
=
"
\\
DosDevices
\\
"
;
LPWSTR
filename
;
static
const
WCHAR
szDosDevices
[]
=
{
'\\'
,
'D'
,
'o'
,
's'
,
'D'
,
'e'
,
'v'
,
'i'
,
'c'
,
'e'
,
's'
,
'\\'
,
0
};
DOS_FULL_NAME
full_name
;
NTSTATUS
r
;
...
...
@@ -79,20 +79,14 @@ NTSTATUS WINAPI NtOpenFile(
return
STATUS_OBJECT_NAME_NOT_FOUND
;
}
/* create an ascii string from the unicode filename */
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
;
filename
=
ObjectAttributes
->
ObjectName
->
Buffer
;
/* FIXME: DOSFS stuff should call here, not vice-versa */
if
(
strncmp
(
filename
,
szDosDevices
,
strlen
(
szDosDevices
)))
if
(
strncmp
W
(
filename
,
szDosDevices
,
strlenW
(
szDosDevices
)))
return
STATUS_OBJECT_NAME_NOT_FOUND
;
/* FIXME: this calls SetLastError() -> bad */
if
(
!
DOSFS_GetFullName
(
&
filename
[
strlen
(
szDosDevices
)],
TRUE
,
if
(
!
DOSFS_GetFullName
(
&
filename
[
strlen
W
(
szDosDevices
)],
TRUE
,
&
full_name
))
return
STATUS_OBJECT_NAME_NOT_FOUND
;
...
...
@@ -105,7 +99,7 @@ NTSTATUS WINAPI NtOpenFile(
req
->
sharing
=
ShareAccess
;
req
->
create
=
OPEN_EXISTING
;
req
->
attrs
=
0
;
req
->
drive_type
=
GetDriveType
A
(
full_name
.
short_name
);
req
->
drive_type
=
GetDriveType
W
(
full_name
.
short_name
);
wine_server_add_data
(
req
,
full_name
.
long_name
,
strlen
(
full_name
.
long_name
)
);
SetLastError
(
0
);
r
=
wine_server_call
(
req
);
...
...
dlls/winedos/int21.c
View file @
d75aed2c
...
...
@@ -32,16 +32,18 @@
#include "miscemu.h"
#include "msdos.h"
#include "file.h"
#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
int21
);
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
(
DosFileHandleToWin32Handle
(
BX_reg
(
context
))
);
if
(
dev
&&
!
strc
asecmp
(
dev
->
name
,
"EMMXXXX0"
))
{
if
(
dev
&&
!
strc
mpiW
(
dev
->
name
,
emmxxxx0W
))
{
EMS_Ioctl_Handler
(
context
);
return
;
}
...
...
files/directory.c
View file @
d75aed2c
...
...
@@ -41,6 +41,8 @@
#include "wine/winuser16.h"
#include "winerror.h"
#include "winreg.h"
#include "ntddk.h"
#include "wine/unicode.h"
#include "drive.h"
#include "file.h"
#include "heap.h"
...
...
@@ -53,27 +55,30 @@ WINE_DECLARE_DEBUG_CHANNEL(file);
static
DOS_FULL_NAME
DIR_Windows
;
static
DOS_FULL_NAME
DIR_System
;
static
const
WCHAR
wineW
[]
=
{
'w'
,
'i'
,
'n'
,
'e'
,
0
};
/***********************************************************************
* DIR_GetPath
*
* 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
,
DOS_FULL_NAME
*
full_name
,
char
*
longname
,
BOOL
warn
)
static
int
DIR_GetPath
(
LPCWSTR
keyname
,
LPCWSTR
defval
,
DOS_FULL_NAME
*
full_name
,
LPWSTR
longname
,
INT
longname_len
,
BOOL
warn
)
{
char
path
[
MAX_PATHNAME_LEN
];
WCHAR
path
[
MAX_PATHNAME_LEN
];
BY_HANDLE_FILE_INFORMATION
info
;
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
)
||
(
!
FILE_Stat
(
full_name
->
long_name
,
&
info
)
&&
(
mess
=
strerror
(
errno
)))
||
(
!
(
info
.
dwFileAttributes
&
FILE_ATTRIBUTE_DIRECTORY
)
&&
(
mess
=
"not a directory"
))
||
(
!
(
GetLongPathName
A
(
full_name
->
short_name
,
longname
,
MAX_PATHNAME_LEN
)))
)
(
!
(
GetLongPathName
W
(
full_name
->
short_name
,
longname
,
longname_len
)))
)
{
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
1
;
...
...
@@ -86,10 +91,27 @@ static int DIR_GetPath( const char *keyname, const char *defval,
int
DIR_Init
(
void
)
{
char
path
[
MAX_PATHNAME_LEN
];
char
longpath
[
MAX_PATHNAME_LEN
];
WCHAR
longpath
[
MAX_PATHNAME_LEN
];
DOS_FULL_NAME
tmp_dir
,
profile_dir
;
int
drive
;
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
))
{
...
...
@@ -105,13 +127,17 @@ int DIR_Init(void)
}
else
{
WCHAR
szdrive
[
3
]
=
{
drive
+
'A'
,
':'
,
0
};
MultiByteToWideChar
(
DRIVE_GetCodepage
(
drive
),
0
,
cwd
,
-
1
,
longpath
,
MAX_PATHNAME_LEN
);
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
))
||
!
(
DIR_GetPath
(
"system"
,
"c:
\\
windows
\\
system"
,
&
DIR_System
,
longpath
,
TRUE
))
||
!
(
DIR_GetPath
(
"temp"
,
"c:
\\
windows"
,
&
tmp_dir
,
longpath
,
TRUE
)))
if
(
!
(
DIR_GetPath
(
windowsW
,
windows_dirW
,
&
DIR_Windows
,
longpath
,
MAX_PATHNAME_LEN
,
TRUE
))
||
!
(
DIR_GetPath
(
systemW
,
system_dirW
,
&
DIR_System
,
longpath
,
MAX_PATHNAME_LEN
,
TRUE
))
||
!
(
DIR_GetPath
(
tempW
,
windows_dirW
,
&
tmp_dir
,
longpath
,
MAX_PATHNAME_LEN
,
TRUE
)))
{
PROFILE_UsageWineIni
();
return
0
;
...
...
@@ -135,9 +161,8 @@ int DIR_Init(void)
DRIVE_Chdir
(
drive
,
DIR_Windows
.
short_name
+
2
);
}
PROFILE_GetWineIniString
(
"wine"
,
"path"
,
"c:
\\
windows;c:
\\
windows
\\
system"
,
path
,
sizeof
(
path
)
);
if
(
strchr
(
path
,
'/'
))
PROFILE_GetWineIniString
(
wineW
,
pathW
,
path_dirW
,
longpath
,
MAX_PATHNAME_LEN
);
if
(
strchrW
(
longpath
,
'/'
))
{
MESSAGE
(
"Fix your wine config to use DOS drive syntax in [wine] 'Path=' statement! (no '/' allowed)
\n
"
);
PROFILE_UsageWineIni
();
...
...
@@ -146,34 +171,34 @@ int DIR_Init(void)
/* Set the environment variables */
SetEnvironmentVariable
A
(
"PATH"
,
path
);
SetEnvironmentVariable
A
(
"TEMP"
,
tmp_dir
.
short_name
);
SetEnvironmentVariable
A
(
"TMP"
,
tmp_dir
.
short_name
);
SetEnvironmentVariable
A
(
"windir"
,
DIR_Windows
.
short_name
);
SetEnvironmentVariable
A
(
"winsysdir"
,
DIR_System
.
short_name
);
SetEnvironmentVariable
W
(
path_capsW
,
long
path
);
SetEnvironmentVariable
W
(
temp_capsW
,
tmp_dir
.
short_name
);
SetEnvironmentVariable
W
(
tmp_capsW
,
tmp_dir
.
short_name
);
SetEnvironmentVariable
W
(
windirW
,
DIR_Windows
.
short_name
);
SetEnvironmentVariable
W
(
winsysdirW
,
DIR_System
.
short_name
);
/* set COMSPEC only if it doesn't exist already */
if
(
!
GetEnvironmentVariableA
(
"COMSPEC"
,
NULL
,
0
))
SetEnvironmentVariableA
(
"COMSPEC"
,
"c:
\\
command.com"
);
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
"
,
DIR_System
.
short_name
,
DIR_System
.
long_name
);
debugstr_w
(
DIR_System
.
short_name
)
,
DIR_System
.
long_name
);
TRACE
(
"TempDir = %s (%s)
\n
"
,
tmp_dir
.
short_name
,
tmp_dir
.
long_name
);
TRACE
(
"Path = %s
\n
"
,
path
);
debugstr_w
(
tmp_dir
.
short_name
)
,
tmp_dir
.
long_name
);
TRACE
(
"Path = %s
\n
"
,
debugstr_w
(
longpath
)
);
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
);
SetEnvironmentVariable
A
(
"USERPROFILE"
,
longpath
);
TRACE
(
"USERPROFILE= %s
\n
"
,
debugstr_w
(
longpath
)
);
SetEnvironmentVariable
W
(
userprofileW
,
longpath
);
}
TRACE
(
"SYSTEMROOT = %s
\n
"
,
DIR_Windows
.
short_name
);
SetEnvironmentVariable
A
(
"SYSTEMROOT"
,
DIR_Windows
.
short_name
);
TRACE
(
"SYSTEMROOT = %s
\n
"
,
debugstr_w
(
DIR_Windows
.
short_name
)
);
SetEnvironmentVariable
W
(
systemrootW
,
DIR_Windows
.
short_name
);
return
1
;
}
...
...
@@ -184,15 +209,25 @@ int DIR_Init(void)
*/
UINT
WINAPI
GetTempPathA
(
UINT
count
,
LPSTR
path
)
{
WCHAR
pathW
[
MAX_PATH
];
UINT
ret
;
if
(
!
(
ret
=
GetEnvironmentVariableA
(
"TMP"
,
path
,
count
)))
if
(
!
(
ret
=
GetEnvironmentVariableA
(
"TEMP"
,
path
,
count
)))
if
(
!
(
ret
=
GetCurrentDirectoryA
(
count
,
path
)))
return
0
;
if
(
count
&&
(
ret
<
count
-
1
)
&&
(
path
[
ret
-
1
]
!=
'\\'
))
ret
=
GetTempPathW
(
MAX_PATH
,
pathW
);
if
(
!
ret
)
return
0
;
if
(
ret
>
MAX_PATH
)
{
SetLastError
(
ERROR_FILENAME_EXCED_RANGE
);
return
0
;
}
ret
=
WideCharToMultiByte
(
CP_ACP
,
0
,
pathW
,
-
1
,
NULL
,
0
,
NULL
,
NULL
);
if
(
ret
<=
count
)
{
path
[
ret
++
]
=
'\\'
;
path
[
ret
]
=
'\0'
;
WideCharToMultiByte
(
CP_ACP
,
0
,
pathW
,
-
1
,
path
,
count
,
NULL
,
NULL
)
;
ret
--
;
/* length without 0 */
}
return
ret
;
}
...
...
@@ -205,16 +240,49 @@ UINT WINAPI GetTempPathW( UINT count, LPWSTR path )
{
static
const
WCHAR
tmp
[]
=
{
'T'
,
'M'
,
'P'
,
0
};
static
const
WCHAR
temp
[]
=
{
'T'
,
'E'
,
'M'
,
'P'
,
0
};
WCHAR
tmp_path
[
MAX_PATH
];
UINT
ret
;
if
(
!
(
ret
=
GetEnvironmentVariableW
(
tmp
,
path
,
count
)))
if
(
!
(
ret
=
GetEnvironmentVariableW
(
temp
,
path
,
count
)))
if
(
!
(
ret
=
GetCurrentDirectoryW
(
count
,
path
)))
TRACE
(
"%u,%p
\n
"
,
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
;
if
(
count
&&
(
ret
<
count
-
1
)
&&
(
path
[
ret
-
1
]
!=
'\\'
))
if
(
ret
>
MAX_PATH
)
{
path
[
ret
++
]
=
'\\'
;
path
[
ret
]
=
'\0'
;
SetLastError
(
ERROR_FILENAME_EXCED_RANGE
)
;
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
;
}
...
...
@@ -278,16 +346,16 @@ UINT16 WINAPI GetWindowsDirectory16( LPSTR path, UINT16 count )
/***********************************************************************
* GetWindowsDirectory
A
(KERNEL32.@)
* GetWindowsDirectory
W
(KERNEL32.@)
*
* See comment for GetWindowsDirectory
W
.
* See comment for GetWindowsDirectory
A
.
*/
UINT
WINAPI
GetWindowsDirectory
A
(
LP
STR
path
,
UINT
count
)
UINT
WINAPI
GetWindowsDirectory
W
(
LPW
STR
path
,
UINT
count
)
{
UINT
len
=
strlen
(
DIR_Windows
.
short_name
)
+
1
;
UINT
len
=
strlen
W
(
DIR_Windows
.
short_name
)
+
1
;
if
(
path
&&
count
>=
len
)
{
strcpy
(
path
,
DIR_Windows
.
short_name
);
strcpy
W
(
path
,
DIR_Windows
.
short_name
);
len
--
;
}
return
len
;
...
...
@@ -295,7 +363,7 @@ UINT WINAPI GetWindowsDirectoryA( LPSTR path, UINT count )
/***********************************************************************
* GetWindowsDirectory
W
(KERNEL32.@)
* GetWindowsDirectory
A
(KERNEL32.@)
*
* Return value:
* 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
* does not touch the buffer.
*/
UINT
WINAPI
GetWindowsDirectory
W
(
LPW
STR
path
,
UINT
count
)
UINT
WINAPI
GetWindowsDirectory
A
(
LP
STR
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
)
{
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
--
;
}
return
len
;
...
...
@@ -343,16 +411,16 @@ UINT16 WINAPI GetSystemDirectory16( LPSTR path, UINT16 count )
/***********************************************************************
* GetSystemDirectory
A
(KERNEL32.@)
* GetSystemDirectory
W
(KERNEL32.@)
*
* See comment for GetWindowsDirectory
W
.
* See comment for GetWindowsDirectory
A
.
*/
UINT
WINAPI
GetSystemDirectory
A
(
LP
STR
path
,
UINT
count
)
UINT
WINAPI
GetSystemDirectory
W
(
LPW
STR
path
,
UINT
count
)
{
UINT
len
=
strlen
(
DIR_System
.
short_name
)
+
1
;
UINT
len
=
strlen
W
(
DIR_System
.
short_name
)
+
1
;
if
(
path
&&
count
>=
len
)
{
strcpy
(
path
,
DIR_System
.
short_name
);
strcpy
W
(
path
,
DIR_System
.
short_name
);
len
--
;
}
return
len
;
...
...
@@ -360,16 +428,16 @@ UINT WINAPI GetSystemDirectoryA( LPSTR path, UINT count )
/***********************************************************************
* GetSystemDirectory
W
(KERNEL32.@)
* GetSystemDirectory
A
(KERNEL32.@)
*
* See comment for GetWindowsDirectory
W
.
* See comment for GetWindowsDirectory
A
.
*/
UINT
WINAPI
GetSystemDirectory
W
(
LPW
STR
path
,
UINT
count
)
UINT
WINAPI
GetSystemDirectory
A
(
LP
STR
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
)
{
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
--
;
}
return
len
;
...
...
@@ -387,7 +455,7 @@ BOOL16 WINAPI CreateDirectory16( LPCSTR path, LPVOID dummy )
/***********************************************************************
* CreateDirectory
A
(KERNEL32.@)
* CreateDirectory
W
(KERNEL32.@)
* RETURNS:
* TRUE : success
* FALSE : failure
...
...
@@ -396,15 +464,22 @@ BOOL16 WINAPI CreateDirectory16( LPCSTR path, LPVOID dummy )
* ERROR_ACCESS_DENIED: on permission problems
* ERROR_FILENAME_EXCED_RANGE: too long filename(s)
*/
BOOL
WINAPI
CreateDirectory
A
(
LPC
STR
path
,
BOOL
WINAPI
CreateDirectory
W
(
LPCW
STR
path
,
LPSECURITY_ATTRIBUTES
lpsecattribs
)
{
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
))
{
TRACE_
(
file
)(
"cannot use device
'%s'!
\n
"
,
path
);
TRACE_
(
file
)(
"cannot use device
%s!
\n
"
,
debugstr_w
(
path
)
);
SetLastError
(
ERROR_ACCESS_DENIED
);
return
FALSE
;
}
...
...
@@ -414,7 +489,14 @@ BOOL WINAPI CreateDirectoryA( LPCSTR path,
/* the FILE_SetDosError() generated error codes don't match the
* CreateDirectory ones for some errnos */
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
;
default:
FILE_SetDosError
();
break
;
}
...
...
@@ -425,14 +507,27 @@ BOOL WINAPI CreateDirectoryA( LPCSTR path,
/***********************************************************************
* CreateDirectory
W
(KERNEL32.@)
* CreateDirectory
A
(KERNEL32.@)
*/
BOOL
WINAPI
CreateDirectory
W
(
LPCW
STR
path
,
BOOL
WINAPI
CreateDirectory
A
(
LPC
STR
path
,
LPSECURITY_ATTRIBUTES
lpsecattribs
)
{
LPSTR
xpath
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
path
);
BOOL
ret
=
CreateDirectoryA
(
xpath
,
lpsecattribs
);
HeapFree
(
GetProcessHeap
(),
0
,
xpath
);
UNICODE_STRING
pathW
;
BOOL
ret
=
FALSE
;
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
;
}
...
...
@@ -467,17 +562,23 @@ BOOL16 WINAPI RemoveDirectory16( LPCSTR path )
/***********************************************************************
* RemoveDirectory
A
(KERNEL32.@)
* RemoveDirectory
W
(KERNEL32.@)
*/
BOOL
WINAPI
RemoveDirectory
A
(
LPC
STR
path
)
BOOL
WINAPI
RemoveDirectory
W
(
LPCW
STR
path
)
{
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
))
{
TRACE_
(
file
)(
"cannot remove device
'%s'!
\n
"
,
path
);
TRACE_
(
file
)(
"cannot remove device
%s!
\n
"
,
debugstr_w
(
path
)
);
SetLastError
(
ERROR_FILE_NOT_FOUND
);
return
FALSE
;
}
...
...
@@ -492,13 +593,26 @@ BOOL WINAPI RemoveDirectoryA( LPCSTR path )
/***********************************************************************
* RemoveDirectory
W
(KERNEL32.@)
* RemoveDirectory
A
(KERNEL32.@)
*/
BOOL
WINAPI
RemoveDirectory
W
(
LPCW
STR
path
)
BOOL
WINAPI
RemoveDirectory
A
(
LPC
STR
path
)
{
LPSTR
xpath
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
path
);
BOOL
ret
=
RemoveDirectoryA
(
xpath
);
HeapFree
(
GetProcessHeap
(),
0
,
xpath
);
UNICODE_STRING
pathW
;
BOOL
ret
=
FALSE
;
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
;
}
...
...
@@ -508,53 +622,58 @@ BOOL WINAPI RemoveDirectoryW( LPCWSTR path )
*
* 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
,
LPC
W
STR
name
,
DOS_FULL_NAME
*
full_name
)
{
LPSTR
p_l
=
full_name
->
long_name
+
strlen
(
dir
->
long_name
)
+
1
;
LP
STR
p_s
=
full_name
->
short_name
+
strlen
(
dir
->
short_name
)
+
1
;
LP
WSTR
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
))
{
SetLastError
(
ERROR_PATH_NOT_FOUND
);
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
),
p_s
,
!
(
DRIVE_GetFlags
(
dir
->
drive
)
&
DRIVE_CASE_SENSITIVE
)
))
return
FALSE
;
full_name
->
drive
=
dir
->
drive
;
strcpy
(
full_name
->
long_name
,
dir
->
long_name
);
p_l
[
-
1
]
=
'/'
;
strcpy
(
full_name
->
short_name
,
dir
->
short_name
);
strcpy
W
(
full_name
->
short_name
,
dir
->
short_name
);
p_s
[
-
1
]
=
'\\'
;
return
TRUE
;
}
static
BOOL
DIR_SearchSemicolonedPaths
(
LPC
STR
name
,
DOS_FULL_NAME
*
full_name
,
LP
STR
pathlist
)
static
BOOL
DIR_SearchSemicolonedPaths
(
LPC
WSTR
name
,
DOS_FULL_NAME
*
full_name
,
LPW
STR
pathlist
)
{
LPSTR
next
,
buffer
=
NULL
;
INT
len
=
strlen
(
name
),
newlen
,
currlen
=
0
;
LP
W
STR
next
,
buffer
=
NULL
;
INT
len
=
strlen
W
(
name
),
newlen
,
currlen
=
0
;
BOOL
ret
=
FALSE
;
next
=
pathlist
;
while
(
!
ret
&&
next
)
{
LPSTR
cur
=
next
;
static
const
WCHAR
bkslashW
[]
=
{
'\\'
,
0
};
LPWSTR
cur
=
next
;
while
(
*
cur
==
';'
)
cur
++
;
if
(
!*
cur
)
break
;
next
=
strchr
(
cur
,
';'
);
next
=
strchr
W
(
cur
,
';'
);
if
(
next
)
*
next
++
=
'\0'
;
newlen
=
strlen
(
cur
)
+
len
+
2
;
newlen
=
strlenW
(
cur
)
+
len
+
2
;
if
(
newlen
>
currlen
)
{
if
(
!
(
buffer
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
buffer
,
newlen
)))
if
(
!
(
buffer
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
buffer
,
newlen
*
sizeof
(
WCHAR
)
)))
goto
done
;
currlen
=
newlen
;
}
strcpy
(
buffer
,
cur
);
strcat
(
buffer
,
"
\\
"
);
strcat
(
buffer
,
name
);
strcpyW
(
buffer
,
cur
);
strcatW
(
buffer
,
bkslashW
);
strcatW
(
buffer
,
name
);
ret
=
DOSFS_GetFullName
(
buffer
,
TRUE
,
full_name
);
}
done:
...
...
@@ -569,17 +688,18 @@ done:
* Helper function for DIR_SearchPath.
* Search in the specified path, or in $PATH if NULL.
*/
static
BOOL
DIR_TryEnvironmentPath
(
LPC
STR
name
,
DOS_FULL_NAME
*
full_name
,
LPC
STR
envpath
)
static
BOOL
DIR_TryEnvironmentPath
(
LPC
WSTR
name
,
DOS_FULL_NAME
*
full_name
,
LPCW
STR
envpath
)
{
LPSTR
path
;
LP
W
STR
path
;
BOOL
ret
=
FALSE
;
DWORD
size
;
static
const
WCHAR
pathW
[]
=
{
'P'
,
'A'
,
'T'
,
'H'
,
0
};
size
=
envpath
?
strlen
(
envpath
)
+
1
:
GetEnvironmentVariableA
(
"PATH"
,
NULL
,
0
);
size
=
envpath
?
strlen
W
(
envpath
)
+
1
:
GetEnvironmentVariableW
(
pathW
,
NULL
,
0
);
if
(
!
size
)
return
FALSE
;
if
(
!
(
path
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
)))
return
FALSE
;
if
(
envpath
)
strcpy
(
path
,
envpath
);
else
if
(
!
GetEnvironmentVariable
A
(
"PATH"
,
path
,
size
))
goto
done
;
if
(
!
(
path
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
*
sizeof
(
WCHAR
)
)))
return
FALSE
;
if
(
envpath
)
strcpy
W
(
path
,
envpath
);
else
if
(
!
GetEnvironmentVariable
W
(
pathW
,
path
,
size
))
goto
done
;
ret
=
DIR_SearchSemicolonedPaths
(
name
,
full_name
,
path
);
...
...
@@ -594,27 +714,28 @@ done:
*
* Helper function for DIR_SearchPath.
*/
static
BOOL
DIR_TryModulePath
(
LPCSTR
name
,
DOS_FULL_NAME
*
full_name
,
BOOL
win32
)
static
BOOL
DIR_TryModulePath
(
LPC
W
STR
name
,
DOS_FULL_NAME
*
full_name
,
BOOL
win32
)
{
/* FIXME: for now, GetModuleFileName
A
can't return more */
/* FIXME: for now, GetModuleFileName
W
can't return more */
/* than OFS_MAXPATHNAME. This may change with Win32. */
char
buffer
[
OFS_MAXPATHNAME
];
LPSTR
p
;
WCHAR
bufferW
[
OFS_MAXPATHNAME
];
LPWSTR
p
;
if
(
!
win32
)
{
char
buffer
[
OFS_MAXPATHNAME
];
if
(
!
GetCurrentTask
())
return
FALSE
;
if
(
!
GetModuleFileName16
(
GetCurrentTask
(),
buffer
,
sizeof
(
buffer
)
))
buffer
[
0
]
=
'\0'
;
return
FALSE
;
MultiByteToWideChar
(
CP_ACP
,
0
,
buffer
,
-
1
,
bufferW
,
OFS_MAXPATHNAME
);
}
else
{
if
(
!
GetModuleFileName
A
(
0
,
buffer
,
sizeof
(
buffer
)
)
)
buffer
[
0
]
=
'\0'
;
if
(
!
GetModuleFileName
W
(
0
,
bufferW
,
OFS_MAXPATHNAME
)
)
return
FALSE
;
}
if
(
!
(
p
=
strrchr
(
buffer
,
'\\'
)))
return
FALSE
;
if
(
sizeof
(
buffer
)
-
(
++
p
-
buffer
)
<=
strlen
(
name
))
return
FALSE
;
strcpy
(
p
,
name
);
return
DOSFS_GetFullName
(
buffer
,
TRUE
,
full_name
);
if
(
!
(
p
=
strrchr
W
(
bufferW
,
'\\'
)))
return
FALSE
;
if
(
OFS_MAXPATHNAME
-
(
++
p
-
bufferW
)
<=
strlenW
(
name
))
return
FALSE
;
strcpy
W
(
p
,
name
);
return
DOSFS_GetFullName
(
buffer
W
,
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.
*/
static
BOOL
DIR_TryAppPath
(
LPCSTR
name
,
DOS_FULL_NAME
*
full_name
)
static
BOOL
DIR_TryAppPath
(
LPC
W
STR
name
,
DOS_FULL_NAME
*
full_name
)
{
HKEY
hkAppPaths
=
0
,
hkApp
=
0
;
char
lpAppName
[
MAX_PATHNAME_LEN
],
lpAppPaths
[
MAX_PATHNAME_LEN
];
LPSTR
lpFileName
;
WCHAR
lpAppName
[
MAX_PATHNAME_LEN
],
lpAppPaths
[
MAX_PATHNAME_LEN
];
LP
W
STR
lpFileName
;
BOOL
res
=
FALSE
;
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
)
return
FALSE
;
if
(
GetModuleFileNameA
(
0
,
lpAppName
,
sizeof
(
lpAppName
))
==
0
)
if
(
!
GetModuleFileNameW
(
0
,
lpAppName
,
MAX_PATHNAME_LEN
)
)
{
WARN
(
"huh, module not found ??
\n
"
);
goto
end
;
}
lpFileName
=
strrchr
(
lpAppName
,
'\\'
);
lpFileName
=
strrchr
W
(
lpAppName
,
'\\'
);
if
(
!
lpFileName
)
goto
end
;
else
lpFileName
++
;
/* skip '\\' */
if
(
RegOpenKey
A
(
hkAppPaths
,
lpFileName
,
&
hkApp
)
!=
ERROR_SUCCESS
)
if
(
RegOpenKey
W
(
hkAppPaths
,
lpFileName
,
&
hkApp
)
!=
ERROR_SUCCESS
)
goto
end
;
count
=
sizeof
(
lpAppPaths
);
if
(
RegQueryValueEx
A
(
hkApp
,
"Path"
,
0
,
&
type
,
(
LPBYTE
)
lpAppPaths
,
&
count
)
!=
ERROR_SUCCESS
)
if
(
RegQueryValueEx
W
(
hkApp
,
PathW
,
0
,
&
type
,
(
LPBYTE
)
lpAppPaths
,
&
count
)
!=
ERROR_SUCCESS
)
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
);
end:
...
...
@@ -667,19 +789,19 @@ end:
*
* FIXME: should return long path names.
*/
DWORD
DIR_SearchPath
(
LPC
STR
path
,
LPCSTR
name
,
LPC
STR
ext
,
DWORD
DIR_SearchPath
(
LPC
WSTR
path
,
LPCWSTR
name
,
LPCW
STR
ext
,
DOS_FULL_NAME
*
full_name
,
BOOL
win32
)
{
LPCSTR
p
;
LPSTR
tmp
=
NULL
;
LPC
W
STR
p
;
LP
W
STR
tmp
=
NULL
;
BOOL
ret
=
TRUE
;
/* First check the supplied parameters */
p
=
strrchr
(
name
,
'.'
);
if
(
p
&&
!
strchr
(
p
,
'/'
)
&&
!
strchr
(
p
,
'\\'
))
p
=
strrchr
W
(
name
,
'.'
);
if
(
p
&&
!
strchr
W
(
p
,
'/'
)
&&
!
strchrW
(
p
,
'\\'
))
ext
=
NULL
;
/* Ignore the specified extension */
if
(
FILE_contains_path
(
name
))
if
(
FILE_contains_path
W
(
name
))
path
=
NULL
;
/* Ignore path if name already contains a path */
if
(
path
&&
!*
path
)
path
=
NULL
;
/* Ignore empty path */
...
...
@@ -687,20 +809,20 @@ DWORD DIR_SearchPath( LPCSTR path, LPCSTR name, LPCSTR ext,
if
(
ext
)
{
DWORD
len
=
strlen
(
name
)
+
strlen
(
ext
);
if
(
!
(
tmp
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
+
1
)))
DWORD
len
=
strlen
W
(
name
)
+
strlenW
(
ext
);
if
(
!
(
tmp
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
len
+
1
)
*
sizeof
(
WCHAR
)
)))
{
SetLastError
(
ERROR_OUTOFMEMORY
);
return
0
;
}
strcpy
(
tmp
,
name
);
strcat
(
tmp
,
ext
);
strcpy
W
(
tmp
,
name
);
strcat
W
(
tmp
,
ext
);
name
=
tmp
;
}
/* If the name contains an explicit path, everything's easy */
if
(
FILE_contains_path
(
name
))
if
(
FILE_contains_path
W
(
name
))
{
ret
=
DOSFS_GetFullName
(
name
,
TRUE
,
full_name
);
goto
done
;
...
...
@@ -751,7 +873,7 @@ done:
/***********************************************************************
* SearchPath
A
[KERNEL32.@]
* SearchPath
W
[KERNEL32.@]
*
* 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)
* (tested on NT 4.0)
*/
DWORD
WINAPI
SearchPath
A
(
LPCSTR
path
,
LPCSTR
name
,
LPC
STR
ext
,
DWORD
buflen
,
LPSTR
buffer
,
LP
STR
*
lastpart
)
DWORD
WINAPI
SearchPath
W
(
LPCWSTR
path
,
LPCWSTR
name
,
LPCW
STR
ext
,
DWORD
buflen
,
LPWSTR
buffer
,
LPW
STR
*
lastpart
)
{
LPSTR
p
,
res
;
LPSTR
res
;
DOS_FULL_NAME
full_name
;
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
);
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
+
strlen
(
DRIVE_GetRoot
(
full_name
.
short_name
[
0
]
-
'A'
));
strlen
(
DRIVE_GetRoot
(
full_name
.
drive
));
while
(
*
res
==
'/'
)
res
++
;
if
(
buflen
)
{
if
(
buflen
>
3
)
lstrcpynA
(
buffer
+
3
,
res
,
buflen
-
3
);
LPWSTR
p
;
if
(
buflen
>
3
)
{
MultiByteToWideChar
(
DRIVE_GetCodepage
(
full_name
.
drive
),
0
,
res
,
-
1
,
buffer
+
3
,
buflen
-
3
);
buffer
[
buflen
-
1
]
=
0
;
}
for
(
p
=
buffer
;
*
p
;
p
++
)
if
(
*
p
==
'/'
)
*
p
=
'\\'
;
if
(
lastpart
)
*
lastpart
=
strrchr
(
buffer
,
'\\'
)
+
1
;
if
(
lastpart
)
*
lastpart
=
strrchr
W
(
buffer
,
'\\'
)
+
1
;
}
TRACE
(
"Returning %
d
\n
"
,
strlen
(
res
)
+
3
);
return
strlen
(
res
)
+
3
;
TRACE
(
"Returning %
s
\n
"
,
debugstr_w
(
buffer
)
);
return
strlen
W
(
buffer
)
;
}
/***********************************************************************
* SearchPath
W
(KERNEL32.@)
* SearchPath
A
(KERNEL32.@)
*/
DWORD
WINAPI
SearchPath
W
(
LPCWSTR
path
,
LPCWSTR
name
,
LPCW
STR
ext
,
DWORD
buflen
,
LPWSTR
buffer
,
LPW
STR
*
lastpart
)
DWORD
WINAPI
SearchPath
A
(
LPCSTR
path
,
LPCSTR
name
,
LPC
STR
ext
,
DWORD
buflen
,
LPSTR
buffer
,
LP
STR
*
lastpart
)
{
LPWSTR
p
;
LPSTR
res
;
DOS_FULL_NAME
full_name
;
LPSTR
pathA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
path
);
LPSTR
nameA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
name
);
LPSTR
extA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
ext
);
DWORD
ret
=
DIR_SearchPath
(
pathA
,
nameA
,
extA
,
&
full_name
,
TRUE
);
HeapFree
(
GetProcessHeap
(),
0
,
extA
);
HeapFree
(
GetProcessHeap
(),
0
,
nameA
);
HeapFree
(
GetProcessHeap
(),
0
,
pathA
);
if
(
!
ret
)
return
0
;
if
(
buflen
>
0
&&
!
MultiByteToWideChar
(
CP_ACP
,
0
,
full_name
.
short_name
,
-
1
,
buffer
,
buflen
))
buffer
[
buflen
-
1
]
=
0
;
res
=
full_name
.
long_name
+
strlen
(
DRIVE_GetRoot
(
full_name
.
short_name
[
0
]
-
'A'
));
while
(
*
res
==
'/'
)
res
++
;
if
(
buflen
)
UNICODE_STRING
pathW
,
nameW
,
extW
;
WCHAR
bufferW
[
MAX_PATH
];
DWORD
ret
,
retW
;
if
(
path
)
RtlCreateUnicodeStringFromAsciiz
(
&
pathW
,
path
);
else
pathW
.
Buffer
=
NULL
;
if
(
name
)
RtlCreateUnicodeStringFromAsciiz
(
&
nameW
,
name
);
else
nameW
.
Buffer
=
NULL
;
if
(
ext
)
RtlCreateUnicodeStringFromAsciiz
(
&
extW
,
ext
);
else
extW
.
Buffer
=
NULL
;
retW
=
SearchPathW
(
pathW
.
Buffer
,
nameW
.
Buffer
,
extW
.
Buffer
,
MAX_PATH
,
bufferW
,
NULL
);
if
(
!
retW
)
ret
=
0
;
else
if
(
retW
>
MAX_PATH
)
{
if
(
buflen
>
3
)
{
if
(
!
MultiByteToWideChar
(
CP_ACP
,
0
,
res
,
-
1
,
buffer
+
3
,
buflen
-
3
))
buffer
[
buflen
-
1
]
=
0
;
}
for
(
p
=
buffer
;
*
p
;
p
++
)
if
(
*
p
==
'/'
)
*
p
=
'\\'
;
if
(
lastpar
t
)
SetLastError
(
ERROR_FILENAME_EXCED_RANGE
);
ret
=
0
;
}
else
{
ret
=
WideCharToMultiByte
(
CP_ACP
,
0
,
bufferW
,
-
1
,
NULL
,
0
,
NULL
,
NULL
)
;
if
(
buflen
>=
re
t
)
{
for
(
p
=
*
lastpart
=
buffer
;
*
p
;
p
++
)
if
(
*
p
==
'\\'
)
*
lastpart
=
p
+
1
;
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.?
*/
static
BOOL
search_alternate_path
(
LPC
STR
dll_path
,
LPCSTR
name
,
LPC
STR
ext
,
static
BOOL
search_alternate_path
(
LPC
WSTR
dll_path
,
LPCWSTR
name
,
LPCW
STR
ext
,
DOS_FULL_NAME
*
full_name
)
{
LPCSTR
p
;
LPSTR
tmp
=
NULL
;
LPC
W
STR
p
;
LP
W
STR
tmp
=
NULL
;
BOOL
ret
=
TRUE
;
/* First check the supplied parameters */
p
=
strrchr
(
name
,
'.'
);
if
(
p
&&
!
strchr
(
p
,
'/'
)
&&
!
strchr
(
p
,
'\\'
))
p
=
strrchr
W
(
name
,
'.'
);
if
(
p
&&
!
strchr
W
(
p
,
'/'
)
&&
!
strchrW
(
p
,
'\\'
))
ext
=
NULL
;
/* Ignore the specified extension */
/* Allocate a buffer for the file name and extension */
if
(
ext
)
{
DWORD
len
=
strlen
(
name
)
+
strlen
(
ext
);
if
(
!
(
tmp
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
+
1
)))
DWORD
len
=
strlen
W
(
name
)
+
strlenW
(
ext
);
if
(
!
(
tmp
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
len
+
1
)
*
sizeof
(
WCHAR
)
)))
{
SetLastError
(
ERROR_OUTOFMEMORY
);
return
0
;
}
strcpy
(
tmp
,
name
);
strcat
(
tmp
,
ext
);
strcpy
W
(
tmp
,
name
);
strcat
W
(
tmp
,
ext
);
name
=
tmp
;
}
...
...
@@ -922,28 +1056,42 @@ static BOOL search_alternate_path(LPCSTR dll_path, LPCSTR name, LPCSTR ext,
*
* NOTES
* 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
buflen
,
LPSTR
buffer
,
LPSTR
*
lastpart
)
{
LPSTR
p
,
res
;
LPSTR
p
;
DOS_FULL_NAME
full_name
;
DWORD
ret
=
0
;
UNICODE_STRING
dll_pathW
,
nameW
,
extW
;
if
(
!
search_alternate_path
(
dll_path
,
name
,
ext
,
&
full_name
))
{
SetLastError
(
ERROR_FILE_NOT_FOUND
);
return
0
;
}
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
(
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
))
{
if
(
buflen
>
3
)
lstrcpynA
(
buffer
+
3
,
res
,
buflen
-
3
);
for
(
p
=
buffer
;
*
p
;
p
++
)
if
(
*
p
==
'/'
)
*
p
=
'\\'
;
if
(
lastpart
)
*
lastpart
=
strrchr
(
buffer
,
'\\'
)
+
1
;
ret
=
WideCharToMultiByte
(
CP_ACP
,
0
,
full_name
.
short_name
,
-
1
,
NULL
,
0
,
NULL
,
NULL
);
if
(
buflen
>=
ret
)
{
WideCharToMultiByte
(
CP_ACP
,
0
,
full_name
.
short_name
,
-
1
,
buffer
,
buflen
,
NULL
,
NULL
);
for
(
p
=
buffer
;
*
p
;
p
++
)
if
(
*
p
==
'/'
)
*
p
=
'\\'
;
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
;
}
files/dos_fs.c
View file @
d75aed2c
...
...
@@ -85,43 +85,40 @@ typedef struct
static
const
DOS_DEVICE
DOSFS_Devices
[]
=
/* name, device flags (see Int 21/AX=0x4400) */
{
{
"CON"
,
0xc0d3
},
{
"PRN"
,
0xa0c0
},
{
"NUL"
,
0x80c4
},
{
"AUX"
,
0x80c0
},
{
"LPT1"
,
0xa0c0
},
{
"LPT2"
,
0xa0c0
},
{
"LPT3"
,
0xa0c0
},
{
"LPT4"
,
0xc0d3
},
{
"COM1"
,
0x80c0
},
{
"COM2"
,
0x80c0
},
{
"COM3"
,
0x80c0
},
{
"COM4"
,
0x80c0
},
{
"SCSIMGR$"
,
0xc0c0
},
{
"HPSCAN"
,
0xc0c0
},
{
"EMMXXXX0"
,
0x0000
}
{
{
'C'
,
'O'
,
'N'
,
0
},
0xc0d3
},
{
{
'P'
,
'R'
,
'N'
,
0
},
0xa0c0
},
{
{
'N'
,
'U'
,
'L'
,
0
},
0x80c4
},
{
{
'A'
,
'U'
,
'X'
,
0
},
0x80c0
},
{
{
'L'
,
'P'
,
'T'
,
'1'
,
0
},
0xa0c0
},
{
{
'L'
,
'P'
,
'T'
,
'2'
,
0
},
0xa0c0
},
{
{
'L'
,
'P'
,
'T'
,
'3'
,
0
},
0xa0c0
},
{
{
'L'
,
'P'
,
'T'
,
'4'
,
0
},
0xc0d3
},
{
{
'C'
,
'O'
,
'M'
,
'1'
,
0
},
0x80c0
},
{
{
'C'
,
'O'
,
'M'
,
'2'
,
0
},
0x80c0
},
{
{
'C'
,
'O'
,
'M'
,
'3'
,
0
},
0x80c0
},
{
{
'C'
,
'O'
,
'M'
,
'4'
,
0
},
0x80c0
},
{
{
'S'
,
'C'
,
'S'
,
'I'
,
'M'
,
'G'
,
'R'
,
'$'
,
0
},
0xc0c0
},
{
{
'H'
,
'P'
,
'S'
,
'C'
,
'A'
,
'N'
,
0
},
0xc0c0
},
{
{
'E'
,
'M'
,
'M'
,
'X'
,
'X'
,
'X'
,
'X'
,
'0'
,
0
},
0x0000
}
};
#define GET_DRIVE(path) \
(((path)[1] == ':') ? FILE_toupper((path)[0]) - 'A' : DOSFS_CurDrive)
/* Directory info for DOSFS_ReadDir
*/
/*
* Directory info for DOSFS_ReadDir
* contains the names of *all* the files in the directory
*/
typedef
struct
{
DIR
*
dir
;
#ifdef VFAT_IOCTL_READDIR_BOTH
int
fd
;
char
short_name
[
12
];
KERNEL_DIRENT
dirent
[
2
];
#endif
int
used
;
int
size
;
char
names
[
1
];
}
DOS_DIR
;
/* Info structure for FindFirstFile handle */
typedef
struct
{
LPSTR
path
;
LPSTR
long_mask
;
LPSTR
short_mask
;
char
*
path
;
/* unix path */
LP
W
STR
long_mask
;
LP
W
STR
short_mask
;
BYTE
attr
;
int
drive
;
int
cur_pos
;
...
...
@@ -148,10 +145,10 @@ static WINE_EXCEPTION_FILTER(page_fault)
* (i.e. contains only valid DOS chars, lower-case only, fits in 8.3 format).
* File name can be terminated by '\0', '\\' or '/'.
*/
static
int
DOSFS_ValidDOSName
(
const
char
*
name
,
int
ignore_case
)
static
int
DOSFS_ValidDOSName
(
LPCWSTR
name
,
int
ignore_case
)
{
static
const
char
invalid_chars
[]
=
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
INVALID_DOS_CHARS
;
const
char
*
p
=
name
;
const
WCHAR
*
p
=
name
;
const
char
*
invalid
=
ignore_case
?
(
invalid_chars
+
26
)
:
invalid_chars
;
int
len
=
0
;
...
...
@@ -165,7 +162,7 @@ static int DOSFS_ValidDOSName( const char *name, int ignore_case )
}
while
(
!
IS_END_OF_NAME
(
*
p
))
{
if
(
strchr
(
invalid
,
*
p
))
return
0
;
/* Invalid char */
if
(
*
p
<
256
&&
strchr
(
invalid
,
(
char
)
*
p
))
return
0
;
/* Invalid char */
if
(
*
p
==
'.'
)
break
;
/* Start of the extension */
if
(
++
len
>
8
)
return
0
;
/* Name too long */
p
++
;
...
...
@@ -176,7 +173,7 @@ static int DOSFS_ValidDOSName( const char *name, int ignore_case )
len
=
0
;
while
(
!
IS_END_OF_NAME
(
*
p
))
{
if
(
strchr
(
invalid
,
*
p
))
return
0
;
/* Invalid char */
if
(
*
p
<
256
&&
strchr
(
invalid
,
(
char
)
*
p
))
return
0
;
/* Invalid char */
if
(
*
p
==
'.'
)
return
0
;
/* Second extension not allowed */
if
(
++
len
>
3
)
return
0
;
/* Extension too long */
p
++
;
...
...
@@ -194,17 +191,19 @@ static int DOSFS_ValidDOSName( const char *name, int ignore_case )
* Return FALSE if the name is not a valid DOS name.
* 'buffer' must be at least 12 characters long.
*/
BOOL
DOSFS_ToDosFCBFormat
(
LPC
STR
name
,
LP
STR
buffer
)
BOOL
DOSFS_ToDosFCBFormat
(
LPC
WSTR
name
,
LPW
STR
buffer
)
{
static
const
char
invalid_chars
[]
=
INVALID_DOS_CHARS
;
const
char
*
p
=
name
;
LPCWSTR
p
=
name
;
int
i
;
/* Check for "." and ".." */
if
(
*
p
==
'.'
)
{
p
++
;
strcpy
(
buffer
,
". "
);
buffer
[
0
]
=
'.'
;
for
(
i
=
1
;
i
<
11
;
i
++
)
buffer
[
i
]
=
' '
;
buffer
[
11
]
=
0
;
if
(
*
p
==
'.'
)
{
buffer
[
1
]
=
'.'
;
...
...
@@ -230,8 +229,8 @@ BOOL DOSFS_ToDosFCBFormat( LPCSTR name, LPSTR buffer )
buffer
[
i
]
=
'?'
;
break
;
default:
if
(
strchr
(
invalid_chars
,
*
p
))
return
FALSE
;
buffer
[
i
]
=
FILE_toupper
(
*
p
);
if
(
*
p
<
256
&&
strchr
(
invalid_chars
,
(
char
)
*
p
))
return
FALSE
;
buffer
[
i
]
=
toupperW
(
*
p
);
p
++
;
break
;
}
...
...
@@ -267,8 +266,8 @@ BOOL DOSFS_ToDosFCBFormat( LPCSTR name, LPSTR buffer )
buffer
[
i
]
=
'?'
;
break
;
default:
if
(
strchr
(
invalid_chars
,
*
p
))
return
FALSE
;
buffer
[
i
]
=
FILE_toupper
(
*
p
);
if
(
*
p
<
256
&&
strchr
(
invalid_chars
,
(
char
)
*
p
))
return
FALSE
;
buffer
[
i
]
=
toupperW
(
*
p
);
p
++
;
break
;
}
...
...
@@ -291,15 +290,15 @@ BOOL DOSFS_ToDosFCBFormat( LPCSTR name, LPSTR buffer )
* File name can be terminated by '\0', '\\' or '/'.
* 'buffer' must be at least 13 characters long.
*/
static
void
DOSFS_ToDosDTAFormat
(
LPC
STR
name
,
LP
STR
buffer
)
static
void
DOSFS_ToDosDTAFormat
(
LPC
WSTR
name
,
LPW
STR
buffer
)
{
char
*
p
;
LPWSTR
p
;
memcpy
(
buffer
,
name
,
8
);
memcpy
(
buffer
,
name
,
8
*
sizeof
(
WCHAR
)
);
p
=
buffer
+
8
;
while
((
p
>
buffer
)
&&
(
p
[
-
1
]
==
' '
))
p
--
;
*
p
++
=
'.'
;
memcpy
(
p
,
name
+
8
,
3
);
memcpy
(
p
,
name
+
8
,
3
*
sizeof
(
WCHAR
)
);
p
+=
3
;
while
(
p
[
-
1
]
==
' '
)
p
--
;
if
(
p
[
-
1
]
==
'.'
)
p
--
;
...
...
@@ -312,7 +311,7 @@ static void DOSFS_ToDosDTAFormat( LPCSTR name, LPSTR buffer )
*
* Check a DOS file name against a mask (both in FCB format).
*/
static
int
DOSFS_MatchShort
(
const
char
*
mask
,
const
char
*
name
)
static
int
DOSFS_MatchShort
(
LPCWSTR
mask
,
LPCWSTR
name
)
{
int
i
;
for
(
i
=
11
;
i
>
0
;
i
--
,
mask
++
,
name
++
)
...
...
@@ -337,13 +336,13 @@ static int DOSFS_MatchShort( const char *mask, const char *name )
* *test1.txt* test1.txt *
* h?l?o*t.dat hellothisisatest.dat *
*/
static
int
DOSFS_MatchLong
(
const
char
*
mask
,
const
char
*
name
,
int
case_sensitive
)
static
int
DOSFS_MatchLong
(
LPCWSTR
mask
,
LPCWSTR
name
,
int
case_sensitive
)
{
const
char
*
lastjoker
=
NULL
;
const
char
*
next_to_retry
=
NULL
;
LPCWSTR
lastjoker
=
NULL
;
LPCWSTR
next_to_retry
=
NULL
;
static
const
WCHAR
asterisk_dot_asterisk
[]
=
{
'*'
,
'.'
,
'*'
,
0
};
if
(
!
strcmp
(
mask
,
"*.*"
))
return
1
;
if
(
!
strcmp
W
(
mask
,
asterisk_dot_asterisk
))
return
1
;
while
(
*
name
&&
*
mask
)
{
if
(
*
mask
==
'*'
)
...
...
@@ -355,7 +354,7 @@ static int DOSFS_MatchLong( const char *mask, const char *name,
/* skip to the next match after the joker(s) */
if
(
case_sensitive
)
while
(
*
name
&&
(
*
name
!=
*
mask
))
name
++
;
else
while
(
*
name
&&
(
FILE_toupper
(
*
name
)
!=
FILE_toupper
(
*
mask
)))
name
++
;
else
while
(
*
name
&&
(
toupperW
(
*
name
)
!=
toupperW
(
*
mask
)))
name
++
;
if
(
!*
name
)
break
;
next_to_retry
=
name
;
...
...
@@ -369,7 +368,7 @@ static int DOSFS_MatchLong( const char *mask, const char *name,
}
else
{
if
(
FILE_toupper
(
*
mask
)
!=
FILE_toupper
(
*
name
))
mismatch
=
1
;
if
(
toupperW
(
*
mask
)
!=
toupperW
(
*
name
))
mismatch
=
1
;
}
if
(
!
mismatch
)
{
...
...
@@ -411,49 +410,161 @@ static int DOSFS_MatchLong( const char *mask, const char *name,
/***********************************************************************
* DOSFS_OpenDir
* DOSFS_AddDirEntry
*
* Used to construct an array of filenames in DOSFS_OpenDir
*/
static
DOS_DIR
*
DOSFS_OpenDir
(
LPCSTR
path
)
static
BOOL
DOSFS_AddDirEntry
(
DOS_DIR
**
dir
,
LPCWSTR
name
,
LPCWSTR
dosname
)
{
DOS_DIR
*
dir
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
dir
)
);
if
(
!
dir
)
int
extra1
=
(
strlenW
(
name
)
+
1
)
*
sizeof
(
WCHAR
);
int
extra2
=
(
strlenW
(
dosname
)
+
1
)
*
sizeof
(
WCHAR
);
/* if we need more, at minimum double the size */
if
(
(
extra1
+
extra2
+
(
*
dir
)
->
used
)
>
(
*
dir
)
->
size
)
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
NULL
;
int
more
=
(
*
dir
)
->
size
;
DOS_DIR
*
t
;
if
(
more
<
(
extra1
+
extra2
))
more
=
extra1
+
extra2
;
t
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
*
dir
,
sizeof
(
**
dir
)
+
(
*
dir
)
->
size
+
more
);
if
(
!
t
)
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
ERR
(
"Out of memory caching directory structure %d %d %d
\n
"
,
(
*
dir
)
->
size
,
more
,
(
*
dir
)
->
used
);
return
FALSE
;
}
(
*
dir
)
=
t
;
(
*
dir
)
->
size
+=
more
;
}
/* Treat empty path as root directory. This simplifies path split into
directory and mask in several other places */
if
(
!*
path
)
path
=
"/"
;
/* at this point, the dir structure is big enough to hold these names */
strcpyW
((
LPWSTR
)
&
(
*
dir
)
->
names
[(
*
dir
)
->
used
],
name
);
(
*
dir
)
->
used
+=
extra1
;
strcpyW
((
LPWSTR
)
&
(
*
dir
)
->
names
[(
*
dir
)
->
used
],
dosname
);
(
*
dir
)
->
used
+=
extra2
;
return
TRUE
;
}
/***********************************************************************
* DOSFS_OpenDir_VFAT
*/
static
BOOL
DOSFS_OpenDir_VFAT
(
UINT
codepage
,
DOS_DIR
**
dir
,
const
char
*
unix_path
)
{
#ifdef VFAT_IOCTL_READDIR_BOTH
KERNEL_DIRENT
de
[
2
];
int
fd
=
open
(
unix_path
,
O_RDONLY
);
BOOL
r
=
TRUE
;
/* Check if the VFAT ioctl is supported on this directory */
if
((
dir
->
fd
=
open
(
path
,
O_RDONLY
))
!=
-
1
)
if
(
fd
<
0
)
return
FALSE
;
while
(
1
)
{
if
(
ioctl
(
dir
->
fd
,
VFAT_IOCTL_READDIR_BOTH
,
(
long
)
dir
->
dirent
)
==
-
1
)
{
close
(
dir
->
fd
);
dir
->
fd
=
-
1
;
}
WCHAR
long_name
[
MAX_PATH
];
WCHAR
short_name
[
12
];
r
=
(
ioctl
(
fd
,
VFAT_IOCTL_READDIR_BOTH
,
(
long
)
de
)
!=
-
1
);
if
(
!
r
)
break
;
if
(
!
de
[
0
].
d_reclen
)
break
;
MultiByteToWideChar
(
codepage
,
0
,
de
[
0
].
d_name
,
-
1
,
long_name
,
MAX_PATH
);
if
(
!
DOSFS_ToDosFCBFormat
(
long_name
,
short_name
))
short_name
[
0
]
=
'\0'
;
if
(
de
[
1
].
d_name
[
0
])
MultiByteToWideChar
(
codepage
,
0
,
de
[
1
].
d_name
,
-
1
,
long_name
,
MAX_PATH
);
else
{
/* Set the file pointer back at the start of the directory */
lseek
(
dir
->
fd
,
0
,
SEEK_SET
);
dir
->
dir
=
NULL
;
return
dir
;
}
MultiByteToWideChar
(
codepage
,
0
,
de
[
0
].
d_name
,
-
1
,
long_name
,
MAX_PATH
);
r
=
DOSFS_AddDirEntry
(
dir
,
long_name
,
short_name
);
if
(
!
r
)
break
;
}
if
(
r
)
{
static
const
WCHAR
empty_strW
[]
=
{
0
};
DOSFS_AddDirEntry
(
dir
,
empty_strW
,
empty_strW
);
}
close
(
fd
);
return
r
;
#else
return
FALSE
;
#endif
/* VFAT_IOCTL_READDIR_BOTH */
}
/***********************************************************************
* DOSFS_OpenDir_Normal
*
* Now use the standard opendir/readdir interface
*/
static
BOOL
DOSFS_OpenDir_Normal
(
UINT
codepage
,
DOS_DIR
**
dir
,
const
char
*
unix_path
)
{
DIR
*
unixdir
=
opendir
(
unix_path
);
BOOL
r
=
TRUE
;
static
const
WCHAR
empty_strW
[]
=
{
0
};
if
(
!
unixdir
)
return
FALSE
;
while
(
1
)
{
WCHAR
long_name
[
MAX_PATH
];
struct
dirent
*
de
=
readdir
(
unixdir
);
if
(
!
de
)
break
;
MultiByteToWideChar
(
codepage
,
0
,
de
->
d_name
,
-
1
,
long_name
,
MAX_PATH
);
r
=
DOSFS_AddDirEntry
(
dir
,
long_name
,
empty_strW
);
if
(
!
r
)
break
;
}
if
(
r
)
DOSFS_AddDirEntry
(
dir
,
empty_strW
,
empty_strW
);
closedir
(
unixdir
);
return
r
;
}
/***********************************************************************
* DOSFS_OpenDir
*/
static
DOS_DIR
*
DOSFS_OpenDir
(
UINT
codepage
,
const
char
*
unix_path
)
{
const
int
init_size
=
0x100
;
DOS_DIR
*
dir
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
dir
)
+
init_size
);
BOOL
r
;
TRACE
(
"%s
\n
"
,
debugstr_a
(
unix_path
));
if
(
!
dir
)
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
NULL
;
}
dir
->
used
=
0
;
dir
->
size
=
init_size
;
/* Treat empty path as root directory. This simplifies path split into
directory and mask in several other places */
if
(
!*
unix_path
)
unix_path
=
"/"
;
r
=
DOSFS_OpenDir_VFAT
(
codepage
,
&
dir
,
unix_path
);
/* Now use the standard opendir/readdir interface */
if
(
!
r
)
r
=
DOSFS_OpenDir_Normal
(
codepage
,
&
dir
,
unix_path
);
if
(
!
(
dir
->
dir
=
opendir
(
path
))
)
if
(
!
r
)
{
HeapFree
(
GetProcessHeap
(),
0
,
dir
);
HeapFree
(
GetProcessHeap
(),
0
,
dir
);
return
NULL
;
}
dir
->
used
=
0
;
return
dir
;
}
...
...
@@ -463,10 +574,6 @@ static DOS_DIR *DOSFS_OpenDir( LPCSTR path )
*/
static
void
DOSFS_CloseDir
(
DOS_DIR
*
dir
)
{
#ifdef VFAT_IOCTL_READDIR_BOTH
if
(
dir
->
fd
!=
-
1
)
close
(
dir
->
fd
);
#endif
/* VFAT_IOCTL_READDIR_BOTH */
if
(
dir
->
dir
)
closedir
(
dir
->
dir
);
HeapFree
(
GetProcessHeap
(),
0
,
dir
);
}
...
...
@@ -474,29 +581,30 @@ static void DOSFS_CloseDir( DOS_DIR *dir )
/***********************************************************************
* DOSFS_ReadDir
*/
static
BOOL
DOSFS_ReadDir
(
DOS_DIR
*
dir
,
LPCSTR
*
long_name
,
LPCSTR
*
short_name
)
static
BOOL
DOSFS_ReadDir
(
DOS_DIR
*
dir
,
LPC
W
STR
*
long_name
,
LPC
W
STR
*
short_name
)
{
struct
dirent
*
dirent
;
LPCWSTR
sn
,
ln
;
#ifdef VFAT_IOCTL_READDIR_BOTH
if
(
dir
->
fd
!=
-
1
)
{
if
(
ioctl
(
dir
->
fd
,
VFAT_IOCTL_READDIR_BOTH
,
(
long
)
dir
->
dirent
)
!=
-
1
)
{
if
(
!
dir
->
dirent
[
0
].
d_reclen
)
return
FALSE
;
if
(
!
DOSFS_ToDosFCBFormat
(
dir
->
dirent
[
0
].
d_name
,
dir
->
short_name
))
dir
->
short_name
[
0
]
=
'\0'
;
*
short_name
=
dir
->
short_name
;
if
(
dir
->
dirent
[
1
].
d_name
[
0
])
*
long_name
=
dir
->
dirent
[
1
].
d_name
;
else
*
long_name
=
dir
->
dirent
[
0
].
d_name
;
return
TRUE
;
}
}
#endif
/* VFAT_IOCTL_READDIR_BOTH */
if
(
!
dir
)
return
FALSE
;
/* the long pathname is first */
ln
=
(
LPCWSTR
)
&
dir
->
names
[
dir
->
used
];
if
(
ln
[
0
])
*
long_name
=
ln
;
else
return
FALSE
;
dir
->
used
+=
(
strlenW
(
ln
)
+
1
)
*
sizeof
(
WCHAR
);
/* followed by the short path name */
sn
=
(
LPCWSTR
)
&
dir
->
names
[
dir
->
used
];
if
(
sn
[
0
])
*
short_name
=
sn
;
else
*
short_name
=
NULL
;
dir
->
used
+=
(
strlenW
(
sn
)
+
1
)
*
sizeof
(
WCHAR
);
if
(
!
(
dirent
=
readdir
(
dir
->
dir
)))
return
FALSE
;
*
long_name
=
dirent
->
d_name
;
*
short_name
=
NULL
;
return
TRUE
;
}
...
...
@@ -510,18 +618,22 @@ static BOOL DOSFS_ReadDir( DOS_DIR *dir, LPCSTR *long_name,
* File name can be terminated by '\0', '\\' or '/'.
* 'buffer' must be at least 13 characters long.
*/
static
void
DOSFS_Hash
(
LPC
STR
name
,
LP
STR
buffer
,
BOOL
dir_format
,
static
void
DOSFS_Hash
(
LPC
WSTR
name
,
LPW
STR
buffer
,
BOOL
dir_format
,
BOOL
ignore_case
)
{
static
const
char
invalid_chars
[]
=
INVALID_DOS_CHARS
"~."
;
static
const
char
hash_chars
[
32
]
=
"ABCDEFGHIJKLMNOPQRSTUVWXYZ012345"
;
const
char
*
p
,
*
ext
;
char
*
dst
;
LPCWSTR
p
,
ext
;
LPWSTR
dst
;
unsigned
short
hash
;
int
i
;
if
(
dir_format
)
strcpy
(
buffer
,
" "
);
if
(
dir_format
)
{
for
(
i
=
0
;
i
<
11
;
i
++
)
buffer
[
i
]
=
' '
;
buffer
[
11
]
=
0
;
}
if
(
DOSFS_ValidDOSName
(
name
,
ignore_case
))
{
...
...
@@ -537,13 +649,13 @@ static void DOSFS_Hash( LPCSTR name, LPSTR buffer, BOOL dir_format,
/* Simply copy the name, converting to uppercase */
for
(
dst
=
buffer
;
!
IS_END_OF_NAME
(
*
name
)
&&
(
*
name
!=
'.'
);
name
++
)
*
dst
++
=
FILE_toupper
(
*
name
);
*
dst
++
=
toupperW
(
*
name
);
if
(
*
name
==
'.'
)
{
if
(
dir_format
)
dst
=
buffer
+
8
;
else
*
dst
++
=
'.'
;
for
(
name
++
;
!
IS_END_OF_NAME
(
*
name
);
name
++
)
*
dst
++
=
FILE_toupper
(
*
name
);
*
dst
++
=
toupperW
(
*
name
);
}
if
(
!
dir_format
)
*
dst
=
'\0'
;
return
;
...
...
@@ -555,8 +667,8 @@ static void DOSFS_Hash( LPCSTR name, LPSTR buffer, BOOL dir_format,
if
(
ignore_case
)
{
for
(
p
=
name
,
hash
=
0xbeef
;
!
IS_END_OF_NAME
(
p
[
1
]);
p
++
)
hash
=
(
hash
<<
3
)
^
(
hash
>>
5
)
^
FILE_tolower
(
*
p
)
^
(
FILE_tolower
(
p
[
1
])
<<
8
);
hash
=
(
hash
<<
3
)
^
(
hash
>>
5
)
^
FILE_tolower
(
*
p
);
/* Last character
*/
hash
=
(
hash
<<
3
)
^
(
hash
>>
5
)
^
tolowerW
(
*
p
)
^
(
tolowerW
(
p
[
1
])
<<
8
);
hash
=
(
hash
<<
3
)
^
(
hash
>>
5
)
^
tolowerW
(
*
p
);
/* Last character
*/
}
else
{
...
...
@@ -575,7 +687,7 @@ static void DOSFS_Hash( LPCSTR name, LPSTR buffer, BOOL dir_format,
for
(
i
=
4
,
p
=
name
,
dst
=
buffer
;
i
>
0
;
i
--
,
p
++
)
{
if
(
IS_END_OF_NAME
(
*
p
)
||
(
p
==
ext
))
break
;
*
dst
++
=
strchr
(
invalid_chars
,
*
p
)
?
'_'
:
FILE_toupper
(
*
p
);
*
dst
++
=
(
*
p
<
256
&&
strchr
(
invalid_chars
,
(
char
)
*
p
))
?
'_'
:
toupperW
(
*
p
);
}
/* Pad to 5 chars with '~' */
while
(
i
--
>=
0
)
*
dst
++
=
'~'
;
...
...
@@ -590,7 +702,7 @@ static void DOSFS_Hash( LPCSTR name, LPSTR buffer, BOOL dir_format,
{
if
(
!
dir_format
)
*
dst
++
=
'.'
;
for
(
i
=
3
,
ext
++
;
(
i
>
0
)
&&
!
IS_END_OF_NAME
(
*
ext
);
i
--
,
ext
++
)
*
dst
++
=
strchr
(
invalid_chars
,
*
ext
)
?
'_'
:
FILE_toupper
(
*
ext
);
*
dst
++
=
(
*
ext
<
256
&&
strchr
(
invalid_chars
,
(
char
)
*
ext
))
?
'_'
:
toupperW
(
*
ext
);
}
if
(
!
dir_format
)
*
dst
=
'\0'
;
}
...
...
@@ -608,44 +720,44 @@ static void DOSFS_Hash( LPCSTR name, LPSTR buffer, BOOL dir_format,
* turns out to be larger than that, the function returns FALSE.
* 'short_buf' must be at least 13 characters long.
*/
BOOL
DOSFS_FindUnixName
(
LPCSTR
path
,
LPCSTR
name
,
LPSTR
long_buf
,
INT
long_len
,
LP
STR
short_buf
,
BOOL
ignore_case
)
BOOL
DOSFS_FindUnixName
(
const
DOS_FULL_NAME
*
path
,
LPCWSTR
name
,
char
*
long_buf
,
INT
long_len
,
LPW
STR
short_buf
,
BOOL
ignore_case
)
{
DOS_DIR
*
dir
;
LPCSTR
long_name
,
short_name
;
char
dos_name
[
12
],
tmp_buf
[
13
];
LPC
W
STR
long_name
,
short_name
;
WCHAR
dos_name
[
12
],
tmp_buf
[
13
];
BOOL
ret
;
const
char
*
p
=
strchr
(
name
,
'/'
);
int
len
=
p
?
(
int
)(
p
-
name
)
:
strlen
(
name
);
if
((
p
=
strchr
(
name
,
'\\'
)))
len
=
min
(
(
int
)(
p
-
name
),
len
);
LPCWSTR
p
=
strchrW
(
name
,
'/'
);
int
len
=
p
?
(
int
)(
p
-
name
)
:
strlen
W
(
name
);
if
((
p
=
strchr
W
(
name
,
'\\'
)))
len
=
min
(
(
int
)(
p
-
name
),
len
);
/* Ignore trailing dots and spaces */
while
(
len
>
1
&&
(
name
[
len
-
1
]
==
'.'
||
name
[
len
-
1
]
==
' '
))
len
--
;
if
(
long_len
<
len
+
1
)
return
FALSE
;
TRACE
(
"%s,%s
\n
"
,
path
,
name
);
TRACE
(
"%s,%s
\n
"
,
path
->
long_name
,
debugstr_w
(
name
)
);
if
(
!
DOSFS_ToDosFCBFormat
(
name
,
dos_name
))
dos_name
[
0
]
=
'\0'
;
if
(
!
(
dir
=
DOSFS_OpenDir
(
path
)))
if
(
!
(
dir
=
DOSFS_OpenDir
(
DRIVE_GetCodepage
(
path
->
drive
),
path
->
long_name
)))
{
WARN
(
"(%s,%s): can't open dir: %s
\n
"
,
path
,
name
,
strerror
(
errno
)
);
path
->
long_name
,
debugstr_w
(
name
)
,
strerror
(
errno
)
);
return
FALSE
;
}
while
((
ret
=
DOSFS_ReadDir
(
dir
,
&
long_name
,
&
short_name
)))
{
/* Check against Unix name */
if
(
len
==
strlen
(
long_name
))
if
(
len
==
strlen
W
(
long_name
))
{
if
(
!
ignore_case
)
{
if
(
!
strncmp
(
long_name
,
name
,
len
))
break
;
if
(
!
strncmp
W
(
long_name
,
name
,
len
))
break
;
}
else
{
if
(
!
FILE_strncasecmp
(
long_name
,
name
,
len
))
break
;
if
(
!
strncmpiW
(
long_name
,
name
,
len
))
break
;
}
}
if
(
dos_name
[
0
])
...
...
@@ -656,12 +768,13 @@ BOOL DOSFS_FindUnixName( LPCSTR path, LPCSTR name, LPSTR long_buf,
DOSFS_Hash
(
long_name
,
tmp_buf
,
TRUE
,
ignore_case
);
short_name
=
tmp_buf
;
}
if
(
!
strcmp
(
dos_name
,
short_name
))
break
;
if
(
!
strcmp
W
(
dos_name
,
short_name
))
break
;
}
}
if
(
ret
)
{
if
(
long_buf
)
strcpy
(
long_buf
,
long_name
);
if
(
long_buf
)
WideCharToMultiByte
(
DRIVE_GetCodepage
(
path
->
drive
),
0
,
long_name
,
-
1
,
long_buf
,
long_len
,
NULL
,
NULL
);
if
(
short_buf
)
{
if
(
short_name
)
...
...
@@ -669,11 +782,11 @@ BOOL DOSFS_FindUnixName( LPCSTR path, LPCSTR name, LPSTR long_buf,
else
DOSFS_Hash
(
long_name
,
short_buf
,
FALSE
,
ignore_case
);
}
TRACE
(
"(%s,%s) -> %s (%s)
\n
"
,
path
,
name
,
long_name
,
short_buf
?
short_buf
:
"***"
);
TRACE
(
"(%s,%s) -> %s (%s)
\n
"
,
path
->
long_name
,
debugstr_w
(
name
),
debugstr_w
(
long_name
),
short_buf
?
debugstr_w
(
short_buf
)
:
"***"
);
}
else
WARN
(
"
'%s' not found in '%s'
\n
"
,
name
,
path
);
WARN
(
"
%s not found in '%s'
\n
"
,
debugstr_w
(
name
),
path
->
long_name
);
DOSFS_CloseDir
(
dir
);
return
ret
;
}
...
...
@@ -684,21 +797,21 @@ BOOL DOSFS_FindUnixName( LPCSTR path, LPCSTR name, LPSTR long_buf,
*
* Check if a DOS file name represents a DOS device and return the device.
*/
const
DOS_DEVICE
*
DOSFS_GetDevice
(
const
char
*
name
)
const
DOS_DEVICE
*
DOSFS_GetDevice
(
LPCWSTR
name
)
{
unsigned
int
i
;
const
char
*
p
;
const
WCHAR
*
p
;
if
(
!
name
)
return
NULL
;
/* if FILE_DupUnixHandle was used */
if
(
name
[
0
]
&&
(
name
[
1
]
==
':'
))
name
+=
2
;
if
((
p
=
strrchr
(
name
,
'/'
)))
name
=
p
+
1
;
if
((
p
=
strrchr
(
name
,
'\\'
)))
name
=
p
+
1
;
if
((
p
=
strrchr
W
(
name
,
'/'
)))
name
=
p
+
1
;
if
((
p
=
strrchr
W
(
name
,
'\\'
)))
name
=
p
+
1
;
for
(
i
=
0
;
i
<
sizeof
(
DOSFS_Devices
)
/
sizeof
(
DOSFS_Devices
[
0
]);
i
++
)
{
const
char
*
dev
=
DOSFS_Devices
[
i
].
name
;
if
(
!
FILE_strncasecmp
(
dev
,
name
,
strlen
(
dev
)
))
const
WCHAR
*
dev
=
DOSFS_Devices
[
i
].
name
;
if
(
!
strncmpiW
(
dev
,
name
,
strlenW
(
dev
)
))
{
p
=
name
+
strlen
(
dev
);
p
=
name
+
strlen
W
(
dev
);
if
(
!*
p
||
(
*
p
==
'.'
)
||
(
*
p
==
':'
))
return
&
DOSFS_Devices
[
i
];
}
}
...
...
@@ -730,18 +843,23 @@ const DOS_DEVICE *DOSFS_GetDeviceByHandle( HANDLE hFile )
/**************************************************************************
* DOSFS_CreateCommPort
*/
static
HANDLE
DOSFS_CreateCommPort
(
LPCSTR
name
,
DWORD
access
,
DWORD
attributes
,
LPSECURITY_ATTRIBUTES
sa
)
static
HANDLE
DOSFS_CreateCommPort
(
LPC
W
STR
name
,
DWORD
access
,
DWORD
attributes
,
LPSECURITY_ATTRIBUTES
sa
)
{
HANDLE
ret
;
char
devname
[
40
];
WCHAR
devnameW
[
40
];
static
const
WCHAR
serialportsW
[]
=
{
's'
,
'e'
,
'r'
,
'i'
,
'a'
,
'l'
,
'p'
,
'o'
,
'r'
,
't'
,
's'
,
0
};
static
const
WCHAR
empty_strW
[]
=
{
0
};
TRACE_
(
file
)(
"%s %lx %lx
\n
"
,
name
,
access
,
attributes
);
TRACE_
(
file
)(
"%s %lx %lx
\n
"
,
debugstr_w
(
name
)
,
access
,
attributes
);
PROFILE_GetWineIniString
(
"serialports"
,
name
,
""
,
devname
,
sizeof
devname
);
if
(
!
devname
[
0
])
PROFILE_GetWineIniString
(
serialportsW
,
name
,
empty_strW
,
devnameW
,
40
);
if
(
!
devname
W
[
0
])
return
0
;
TRACE
(
"opening %s as %s
\n
"
,
devname
,
name
);
WideCharToMultiByte
(
CP_ACP
,
0
,
devnameW
,
-
1
,
devname
,
sizeof
(
devname
),
NULL
,
NULL
);
TRACE
(
"opening %s as %s
\n
"
,
devname
,
debugstr_w
(
name
));
SERVER_START_REQ
(
create_serial
)
{
...
...
@@ -769,28 +887,33 @@ static HANDLE DOSFS_CreateCommPort(LPCSTR name, DWORD access, DWORD attributes,
* Open a DOS device. This might not map 1:1 into the UNIX device concept.
* Returns 0 on failure.
*/
HANDLE
DOSFS_OpenDevice
(
const
char
*
name
,
DWORD
access
,
DWORD
attributes
,
LPSECURITY_ATTRIBUTES
sa
)
HANDLE
DOSFS_OpenDevice
(
LPCWSTR
name
,
DWORD
access
,
DWORD
attributes
,
LPSECURITY_ATTRIBUTES
sa
)
{
unsigned
int
i
;
const
char
*
p
;
const
WCHAR
*
p
;
HANDLE
handle
;
if
(
name
[
0
]
&&
(
name
[
1
]
==
':'
))
name
+=
2
;
if
((
p
=
strrchr
(
name
,
'/'
)))
name
=
p
+
1
;
if
((
p
=
strrchr
(
name
,
'\\'
)))
name
=
p
+
1
;
if
((
p
=
strrchr
W
(
name
,
'/'
)))
name
=
p
+
1
;
if
((
p
=
strrchr
W
(
name
,
'\\'
)))
name
=
p
+
1
;
for
(
i
=
0
;
i
<
sizeof
(
DOSFS_Devices
)
/
sizeof
(
DOSFS_Devices
[
0
]);
i
++
)
{
const
char
*
dev
=
DOSFS_Devices
[
i
].
name
;
if
(
!
FILE_strncasecmp
(
dev
,
name
,
strlen
(
dev
)
))
const
WCHAR
*
dev
=
DOSFS_Devices
[
i
].
name
;
if
(
!
strncmpiW
(
dev
,
name
,
strlenW
(
dev
)
))
{
p
=
name
+
strlen
(
dev
);
p
=
name
+
strlen
W
(
dev
);
if
(
!*
p
||
(
*
p
==
'.'
)
||
(
*
p
==
':'
))
{
static
const
WCHAR
nulW
[]
=
{
'N'
,
'U'
,
'L'
,
0
};
static
const
WCHAR
conW
[]
=
{
'C'
,
'O'
,
'N'
,
0
};
static
const
WCHAR
scsimgrW
[]
=
{
'S'
,
'C'
,
'S'
,
'I'
,
'M'
,
'G'
,
'R'
,
'$'
,
0
};
static
const
WCHAR
hpscanW
[]
=
{
'H'
,
'P'
,
'S'
,
'C'
,
'A'
,
'N'
,
0
};
static
const
WCHAR
emmxxxx0W
[]
=
{
'E'
,
'M'
,
'M'
,
'X'
,
'X'
,
'X'
,
'X'
,
'0'
,
0
};
/* got it */
if
(
!
strcmp
(
DOSFS_Devices
[
i
].
name
,
"NUL"
))
if
(
!
strcmp
iW
(
DOSFS_Devices
[
i
].
name
,
nulW
))
return
FILE_CreateFile
(
"/dev/null"
,
access
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
sa
,
OPEN_EXISTING
,
0
,
0
,
TRUE
,
DRIVE_UNKNOWN
);
if
(
!
strcmp
(
DOSFS_Devices
[
i
].
name
,
"CON"
))
{
if
(
!
strcmp
iW
(
DOSFS_Devices
[
i
].
name
,
conW
))
{
HANDLE
to_dup
;
switch
(
access
&
(
GENERIC_READ
|
GENERIC_WRITE
))
{
case
GENERIC_READ
:
...
...
@@ -810,16 +933,16 @@ HANDLE DOSFS_OpenDevice( const char *name, DWORD access, DWORD attributes, LPSEC
handle
=
0
;
return
handle
;
}
if
(
!
strcmp
(
DOSFS_Devices
[
i
].
name
,
"SCSIMGR$"
)
||
!
strcmp
(
DOSFS_Devices
[
i
].
name
,
"HPSCAN"
)
||
!
strcmp
(
DOSFS_Devices
[
i
].
name
,
"EMMXXXX0"
))
if
(
!
strcmp
iW
(
DOSFS_Devices
[
i
].
name
,
scsimgrW
)
||
!
strcmp
iW
(
DOSFS_Devices
[
i
].
name
,
hpscanW
)
||
!
strcmp
iW
(
DOSFS_Devices
[
i
].
name
,
emmxxxx0W
))
{
return
FILE_CreateDevice
(
i
,
access
,
sa
);
}
if
(
(
handle
=
DOSFS_CreateCommPort
(
DOSFS_Devices
[
i
].
name
,
access
,
attributes
,
sa
))
)
return
handle
;
FIXME
(
"device open %s not supported (yet)
\n
"
,
DOSFS_Devices
[
i
].
name
);
FIXME
(
"device open %s not supported (yet)
\n
"
,
debugstr_w
(
DOSFS_Devices
[
i
].
name
)
);
return
0
;
}
}
...
...
@@ -833,21 +956,21 @@ HANDLE DOSFS_OpenDevice( const char *name, DWORD access, DWORD attributes, LPSEC
*
* Get the drive specified by a given path name (DOS or Unix format).
*/
static
int
DOSFS_GetPathDrive
(
const
char
*
*
name
)
static
int
DOSFS_GetPathDrive
(
LPCWSTR
*
name
)
{
int
drive
;
const
char
*
p
=
*
name
;
LPCWSTR
p
=
*
name
;
if
(
*
p
&&
(
p
[
1
]
==
':'
))
{
drive
=
FILE_toupper
(
*
p
)
-
'A'
;
drive
=
toupperW
(
*
p
)
-
'A'
;
*
name
+=
2
;
}
else
if
(
*
p
==
'/'
)
/* Absolute Unix path? */
{
if
((
drive
=
DRIVE_FindDriveRoot
(
name
))
==
-
1
)
if
((
drive
=
DRIVE_FindDriveRoot
W
(
name
))
==
-
1
)
{
MESSAGE
(
"Warning: %s not accessible from a configured DOS drive
\n
"
,
*
name
);
MESSAGE
(
"Warning: %s not accessible from a configured DOS drive
\n
"
,
debugstr_w
(
*
name
)
);
/* Assume it really was a DOS name */
drive
=
DRIVE_GetCurrentDrive
();
}
...
...
@@ -873,13 +996,16 @@ static int DOSFS_GetPathDrive( const char **name )
* The buffers pointed to by 'long_buf' and 'short_buf' must be
* at least MAX_PATHNAME_LEN long.
*/
BOOL
DOSFS_GetFullName
(
LPCSTR
name
,
BOOL
check_last
,
DOS_FULL_NAME
*
full
)
BOOL
DOSFS_GetFullName
(
LPC
W
STR
name
,
BOOL
check_last
,
DOS_FULL_NAME
*
full
)
{
BOOL
found
;
UINT
flags
;
char
*
p_l
,
*
p_s
,
*
root
;
UINT
flags
,
codepage
;
char
*
p_l
,
*
root
;
LPWSTR
p_s
;
static
const
WCHAR
driveA_rootW
[]
=
{
'A'
,
':'
,
'\\'
,
0
};
static
const
WCHAR
dos_rootW
[]
=
{
'\\'
,
0
};
TRACE
(
"%s (last=%d)
\n
"
,
name
,
check_last
);
TRACE
(
"%s (last=%d)
\n
"
,
debugstr_w
(
name
)
,
check_last
);
if
((
!*
name
)
||
(
*
name
==
'\n'
))
{
/* error code for Win98 */
...
...
@@ -889,13 +1015,14 @@ BOOL DOSFS_GetFullName( LPCSTR name, BOOL check_last, DOS_FULL_NAME *full )
if
((
full
->
drive
=
DOSFS_GetPathDrive
(
&
name
))
==
-
1
)
return
FALSE
;
flags
=
DRIVE_GetFlags
(
full
->
drive
);
codepage
=
DRIVE_GetCodepage
(
full
->
drive
);
lstrcpynA
(
full
->
long_name
,
DRIVE_GetRoot
(
full
->
drive
),
sizeof
(
full
->
long_name
)
);
if
(
full
->
long_name
[
1
])
root
=
full
->
long_name
+
strlen
(
full
->
long_name
);
else
root
=
full
->
long_name
;
/* root directory */
strcpy
(
full
->
short_name
,
"A:
\\
"
);
strcpy
W
(
full
->
short_name
,
driveA_rootW
);
full
->
short_name
[
0
]
+=
full
->
drive
;
if
((
*
name
==
'\\'
)
||
(
*
name
==
'/'
))
/* Absolute path */
...
...
@@ -907,13 +1034,13 @@ BOOL DOSFS_GetFullName( LPCSTR name, BOOL check_last, DOS_FULL_NAME *full )
lstrcpynA
(
root
+
1
,
DRIVE_GetUnixCwd
(
full
->
drive
),
sizeof
(
full
->
long_name
)
-
(
root
-
full
->
long_name
)
-
1
);
if
(
root
[
1
])
*
root
=
'/'
;
lstrcpyn
A
(
full
->
short_name
+
3
,
DRIVE_GetDosCwd
(
full
->
drive
),
sizeof
(
full
->
short_name
)
-
3
);
lstrcpyn
W
(
full
->
short_name
+
3
,
DRIVE_GetDosCwd
(
full
->
drive
),
sizeof
(
full
->
short_name
)
/
sizeof
(
full
->
short_name
[
0
]
)
-
3
);
}
p_l
=
full
->
long_name
[
1
]
?
full
->
long_name
+
strlen
(
full
->
long_name
)
:
full
->
long_name
;
p_s
=
full
->
short_name
[
3
]
?
full
->
short_name
+
strlen
(
full
->
short_name
)
p_s
=
full
->
short_name
[
3
]
?
full
->
short_name
+
strlen
W
(
full
->
short_name
)
:
full
->
short_name
+
2
;
found
=
TRUE
;
...
...
@@ -942,7 +1069,7 @@ BOOL DOSFS_GetFullName( LPCSTR name, BOOL check_last, DOS_FULL_NAME *full )
/* Make sure buffers are large enough */
if
((
p_s
>=
full
->
short_name
+
sizeof
(
full
->
short_name
)
-
14
)
||
if
((
p_s
>=
full
->
short_name
+
sizeof
(
full
->
short_name
)
/
sizeof
(
full
->
short_name
[
0
])
-
14
)
||
(
p_l
>=
full
->
long_name
+
sizeof
(
full
->
long_name
)
-
1
))
{
SetLastError
(
ERROR_PATH_NOT_FOUND
);
...
...
@@ -951,14 +1078,14 @@ BOOL DOSFS_GetFullName( LPCSTR name, BOOL check_last, DOS_FULL_NAME *full )
/* Get the long and short name matching the file name */
if
((
found
=
DOSFS_FindUnixName
(
full
->
long_name
,
name
,
p_l
+
1
,
if
((
found
=
DOSFS_FindUnixName
(
full
,
name
,
p_l
+
1
,
sizeof
(
full
->
long_name
)
-
(
p_l
-
full
->
long_name
)
-
1
,
p_s
+
1
,
!
(
flags
&
DRIVE_CASE_SENSITIVE
)
)))
{
*
p_l
++
=
'/'
;
p_l
+=
strlen
(
p_l
);
*
p_s
++
=
'\\'
;
p_s
+=
strlen
(
p_s
);
p_s
+=
strlen
W
(
p_s
);
while
(
!
IS_END_OF_NAME
(
*
name
))
name
++
;
}
else
if
(
!
check_last
)
...
...
@@ -966,15 +1093,17 @@ BOOL DOSFS_GetFullName( LPCSTR name, BOOL check_last, DOS_FULL_NAME *full )
*
p_l
++
=
'/'
;
*
p_s
++
=
'\\'
;
while
(
!
IS_END_OF_NAME
(
*
name
)
&&
(
p_s
<
full
->
short_name
+
sizeof
(
full
->
short_name
)
-
1
)
&&
(
p_s
<
full
->
short_name
+
sizeof
(
full
->
short_name
)
/
sizeof
(
full
->
short_name
[
0
])
-
1
)
&&
(
p_l
<
full
->
long_name
+
sizeof
(
full
->
long_name
)
-
1
))
{
*
p_s
++
=
FILE_tolower
(
*
name
);
WCHAR
wch
;
*
p_s
++
=
tolowerW
(
*
name
);
/* If the drive is case-sensitive we want to create new */
/* files in lower-case otherwise we can't reopen them */
/* under the same short name. */
if
(
flags
&
DRIVE_CASE_SENSITIVE
)
*
p_l
++
=
FILE_tolower
(
*
name
);
else
*
p_l
++
=
*
name
;
if
(
flags
&
DRIVE_CASE_SENSITIVE
)
wch
=
tolowerW
(
*
name
);
else
wch
=
*
name
;
p_l
+=
WideCharToMultiByte
(
codepage
,
0
,
&
wch
,
1
,
p_l
,
2
,
NULL
,
NULL
);
name
++
;
}
/* Ignore trailing dots and spaces */
...
...
@@ -982,7 +1111,8 @@ BOOL DOSFS_GetFullName( LPCSTR name, BOOL check_last, DOS_FULL_NAME *full )
--
p_l
;
--
p_s
;
}
*
p_l
=
*
p_s
=
'\0'
;
*
p_l
=
'\0'
;
*
p_s
=
'\0'
;
}
while
((
*
name
==
'\\'
)
||
(
*
name
==
'/'
))
name
++
;
}
...
...
@@ -1001,14 +1131,14 @@ BOOL DOSFS_GetFullName( LPCSTR name, BOOL check_last, DOS_FULL_NAME *full )
}
}
if
(
!
full
->
long_name
[
0
])
strcpy
(
full
->
long_name
,
"/"
);
if
(
!
full
->
short_name
[
2
])
strcpy
(
full
->
short_name
+
2
,
"
\\
"
);
TRACE
(
"returning %s = %s
\n
"
,
full
->
long_name
,
full
->
short_name
);
if
(
!
full
->
short_name
[
2
])
strcpy
W
(
full
->
short_name
+
2
,
dos_rootW
);
TRACE
(
"returning %s = %s
\n
"
,
full
->
long_name
,
debugstr_w
(
full
->
short_name
)
);
return
TRUE
;
}
/***********************************************************************
* GetShortPathName
A
(KERNEL32.@)
* GetShortPathName
W
(KERNEL32.@)
*
* NOTES
* observed:
...
...
@@ -1027,17 +1157,18 @@ BOOL DOSFS_GetFullName( LPCSTR name, BOOL check_last, DOS_FULL_NAME *full )
* - longpath and shortpath may have the same address
* Peter Ganten, 1999
*/
DWORD
WINAPI
GetShortPathNameA
(
LPCSTR
longpath
,
LPSTR
shortpath
,
DWORD
shortlen
)
DWORD
WINAPI
GetShortPathNameW
(
LPCWSTR
longpath
,
LPWSTR
shortpath
,
DWORD
shortlen
)
{
DOS_FULL_NAME
full_name
;
LPSTR
tmpshortpath
;
WCHAR
tmpshortpath
[
MAX_PATHNAME_LEN
];
const
WCHAR
*
p
;
DWORD
sp
=
0
,
lp
=
0
;
int
tmplen
,
drive
;
int
drive
;
DWORD
tmplen
;
UINT
flags
;
BOOL
unixabsolute
=
*
longpath
==
'/'
;
TRACE
(
"%s
\n
"
,
debugstr_
a
(
longpath
));
TRACE
(
"%s
\n
"
,
debugstr_
w
(
longpath
));
if
(
!
longpath
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
...
...
@@ -1048,11 +1179,6 @@ DWORD WINAPI GetShortPathNameA( LPCSTR longpath, LPSTR shortpath,
return
0
;
}
if
(
(
tmpshortpath
=
HeapAlloc
(
GetProcessHeap
(),
0
,
MAX_PATHNAME_LEN
)
)
==
NULL
)
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
0
;
}
/* check for drive letter */
if
(
!
unixabsolute
&&
longpath
[
1
]
==
':'
)
{
tmpshortpath
[
0
]
=
longpath
[
0
];
...
...
@@ -1084,8 +1210,10 @@ DWORD WINAPI GetShortPathNameA( LPCSTR longpath, LPSTR shortpath,
continue
;
}
tmplen
=
strcspn
(
longpath
+
lp
,
"
\\
/"
);
lstrcpynA
(
tmpshortpath
+
sp
,
longpath
+
lp
,
tmplen
+
1
);
tmplen
=
0
;
for
(
p
=
longpath
+
lp
;
*
p
&&
*
p
!=
'/'
&&
*
p
!=
'\\'
;
p
++
)
tmplen
++
;
lstrcpynW
(
tmpshortpath
+
sp
,
longpath
+
lp
,
tmplen
+
1
);
/* Check, if the current element is a valid dos name */
if
(
DOSFS_ValidDOSName
(
longpath
+
lp
,
!
(
flags
&
DRIVE_CASE_SENSITIVE
)
)
)
{
...
...
@@ -1096,8 +1224,8 @@ DWORD WINAPI GetShortPathNameA( LPCSTR longpath, LPSTR shortpath,
/* Check if the file exists and use the existing file name */
if
(
DOSFS_GetFullName
(
tmpshortpath
,
TRUE
,
&
full_name
)
)
{
strcpy
(
tmpshortpath
+
sp
,
strrchr
(
full_name
.
short_name
,
'\\'
)
+
1
);
sp
+=
strlen
(
tmpshortpath
+
sp
);
strcpy
W
(
tmpshortpath
+
sp
,
strrchrW
(
full_name
.
short_name
,
'\\'
)
+
1
);
sp
+=
strlen
W
(
tmpshortpath
+
sp
);
lp
+=
tmplen
;
continue
;
}
...
...
@@ -1108,50 +1236,81 @@ DWORD WINAPI GetShortPathNameA( LPCSTR longpath, LPSTR shortpath,
}
tmpshortpath
[
sp
]
=
0
;
lstrcpynA
(
shortpath
,
tmpshortpath
,
shortlen
);
TRACE
(
"returning %s
\n
"
,
debugstr_a
(
shortpath
)
);
tmplen
=
strlen
(
tmpshortpath
);
HeapFree
(
GetProcessHeap
(),
0
,
tmpshortpath
);
tmplen
=
strlenW
(
tmpshortpath
)
+
1
;
if
(
tmplen
<=
shortlen
)
{
strcpyW
(
shortpath
,
tmpshortpath
);
TRACE
(
"returning %s
\n
"
,
debugstr_w
(
shortpath
));
tmplen
--
;
/* length without 0 */
}
return
tmplen
;
}
/***********************************************************************
* GetShortPathName
W
(KERNEL32.@)
* GetShortPathName
A
(KERNEL32.@)
*/
DWORD
WINAPI
GetShortPathNameW
(
LPCWSTR
longpath
,
LPWSTR
shortpath
,
DWORD
shortlen
)
DWORD
WINAPI
GetShortPathNameA
(
LPCSTR
longpath
,
LPSTR
shortpath
,
DWORD
shortlen
)
{
LPSTR
longpathA
,
shortpathA
;
DWORD
ret
=
0
;
UNICODE_STRING
longpathW
;
WCHAR
shortpathW
[
MAX_PATH
];
DWORD
ret
,
retW
;
if
(
!
longpath
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
0
;
}
longpathA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
longpath
);
shortpathA
=
HeapAlloc
(
GetProcessHeap
(),
0
,
shortlen
);
TRACE
(
"%s
\n
"
,
debugstr_a
(
longpath
));
if
(
!
RtlCreateUnicodeStringFromAsciiz
(
&
longpathW
,
longpath
))
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
0
;
}
ret
=
GetShortPathNameA
(
longpathA
,
shortpathA
,
shortlen
);
if
(
shortlen
>
0
&&
!
MultiByteToWideChar
(
CP_ACP
,
0
,
shortpathA
,
-
1
,
shortpath
,
shortlen
))
shortpath
[
shortlen
-
1
]
=
0
;
HeapFree
(
GetProcessHeap
(),
0
,
longpathA
);
HeapFree
(
GetProcessHeap
(),
0
,
shortpathA
);
retW
=
GetShortPathNameW
(
longpathW
.
Buffer
,
shortpathW
,
MAX_PATH
);
if
(
!
retW
)
ret
=
0
;
else
if
(
retW
>
MAX_PATH
)
{
SetLastError
(
ERROR_FILENAME_EXCED_RANGE
);
ret
=
0
;
}
else
{
ret
=
WideCharToMultiByte
(
CP_ACP
,
0
,
shortpathW
,
-
1
,
NULL
,
0
,
NULL
,
NULL
);
if
(
ret
<=
shortlen
)
{
WideCharToMultiByte
(
CP_ACP
,
0
,
shortpathW
,
-
1
,
shortpath
,
shortlen
,
NULL
,
NULL
);
ret
--
;
/* length without 0 */
}
}
RtlFreeUnicodeString
(
&
longpathW
);
return
ret
;
}
/***********************************************************************
* GetLongPathName
A
(KERNEL32.@)
* GetLongPathName
W
(KERNEL32.@)
*
* NOTES
* observed (Win2000):
* shortpath=NULL: LastError=ERROR_INVALID_PARAMETER, ret=0
* shortpath="": LastError=ERROR_PATH_NOT_FOUND, ret=0
*/
DWORD
WINAPI
GetLongPathNameA
(
LPCSTR
shortpath
,
LPSTR
longpath
,
DWORD
longlen
)
DWORD
WINAPI
GetLongPathNameW
(
LPCWSTR
shortpath
,
LPWSTR
longpath
,
DWORD
longlen
)
{
DOS_FULL_NAME
full_name
;
char
*
p
,
*
r
,
*
ll
,
*
ss
;
const
char
*
root
;
LPWSTR
p
;
int
drive
;
UINT
codepage
;
DWORD
ret
,
len
=
0
;
if
(
!
shortpath
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
...
...
@@ -1162,79 +1321,92 @@ DWORD WINAPI GetLongPathNameA( LPCSTR shortpath, LPSTR longpath,
return
0
;
}
TRACE
(
"%s,%p,%ld
\n
"
,
debugstr_w
(
shortpath
),
longpath
,
longlen
);
if
(
shortpath
[
0
]
==
'\\'
&&
shortpath
[
1
]
==
'\\'
)
{
ERR
(
"UNC pathname %s
\n
"
,
debugstr_
a
(
shortpath
));
lstrcpyn
A
(
longpath
,
full_name
.
short_name
,
longlen
);
return
lstrlenA
(
longpath
);
ERR
(
"UNC pathname %s
\n
"
,
debugstr_
w
(
shortpath
));
lstrcpyn
W
(
longpath
,
full_name
.
short_name
,
longlen
);
return
strlenW
(
longpath
);
}
if
(
!
DOSFS_GetFullName
(
shortpath
,
TRUE
,
&
full_name
))
return
0
;
lstrcpynA
(
longpath
,
full_name
.
short_name
,
longlen
);
/* Do some hackery to get the long filename. */
if
(
longpath
)
{
ss
=
longpath
+
strlen
(
longpath
);
ll
=
full_name
.
long_name
+
strlen
(
full_name
.
long_name
);
p
=
NULL
;
while
(
ss
>=
longpath
)
{
/* FIXME: aren't we more paranoid, than needed? */
while
((
ss
[
0
]
==
'\\'
)
&&
(
ss
>=
longpath
))
ss
--
;
p
=
ss
;
while
((
ss
[
0
]
!=
'\\'
)
&&
(
ss
>=
longpath
))
ss
--
;
if
(
ss
>=
longpath
)
{
/* FIXME: aren't we more paranoid, than needed? */
while
((
ll
[
0
]
==
'/'
)
&&
(
ll
>=
full_name
.
long_name
))
ll
--
;
while
((
ll
[
0
]
!=
'/'
)
&&
(
ll
>=
full_name
.
long_name
))
ll
--
;
if
(
ll
<
full_name
.
long_name
)
{
ERR
(
"Bad longname! (ss=%s ll=%s)
\n
This should never happen !
\n
"
,
ss
,
ll
);
return
0
;
}
}
}
/* FIXME: fix for names like "C:\\" (ie. with more '\'s) */
if
(
p
&&
p
[
2
])
root
=
full_name
.
long_name
;
drive
=
DRIVE_FindDriveRoot
(
&
root
);
codepage
=
DRIVE_GetCodepage
(
drive
);
ret
=
MultiByteToWideChar
(
codepage
,
0
,
root
,
-
1
,
NULL
,
0
);
ret
+=
3
;
/* A:\ */
/* reproduce terminating slash */
if
(
ret
>
4
)
/* if not drive root */
{
len
=
strlenW
(
shortpath
);
if
(
shortpath
[
len
-
1
]
==
'\\'
||
shortpath
[
len
-
1
]
==
'/'
)
len
=
1
;
}
ret
+=
len
;
if
(
ret
<=
longlen
)
{
longpath
[
0
]
=
'A'
+
drive
;
longpath
[
1
]
=
':'
;
MultiByteToWideChar
(
codepage
,
0
,
root
,
-
1
,
longpath
+
2
,
longlen
-
2
);
for
(
p
=
longpath
;
*
p
;
p
++
)
if
(
*
p
==
'/'
)
*
p
=
'\\'
;
if
(
len
)
{
p
+=
1
;
if
((
p
-
longpath
)
>
0
)
longlen
-=
(
p
-
longpath
);
lstrcpynA
(
p
,
ll
,
longlen
);
/* Now, change all '/' to '\' */
for
(
r
=
p
;
r
<
(
p
+
longlen
);
r
++
)
if
(
r
[
0
]
==
'/'
)
r
[
0
]
=
'\\'
;
return
strlen
(
longpath
)
-
strlen
(
p
)
+
longlen
;
longpath
[
ret
-
2
]
=
'\\'
;
longpath
[
ret
-
1
]
=
0
;
}
TRACE
(
"returning %s
\n
"
,
debugstr_w
(
longpath
));
ret
--
;
/* length without 0 */
}
return
strlen
(
longpath
);
return
ret
;
}
/***********************************************************************
* GetLongPathName
W
(KERNEL32.@)
* GetLongPathName
A
(KERNEL32.@)
*/
DWORD
WINAPI
GetLongPathNameW
(
LPCWSTR
shortpath
,
LPWSTR
longpath
,
DWORD
longlen
)
DWORD
WINAPI
GetLongPathNameA
(
LPCSTR
shortpath
,
LPSTR
longpath
,
DWORD
longlen
)
{
DOS_FULL_NAME
full_name
;
DWORD
ret
=
0
;
LPSTR
shortpathA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
shortpath
);
UNICODE_STRING
shortpathW
;
WCHAR
longpathW
[
MAX_PATH
];
DWORD
ret
,
retW
;
if
(
!
shortpath
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
0
;
}
TRACE
(
"%s
\n
"
,
debugstr_a
(
shortpath
));
if
(
!
RtlCreateUnicodeStringFromAsciiz
(
&
shortpathW
,
shortpath
))
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
0
;
}
/* FIXME: is it correct to always return a fully qualified short path? */
if
(
DOSFS_GetFullName
(
shortpathA
,
TRUE
,
&
full_name
))
retW
=
GetLongPathNameW
(
shortpathW
.
Buffer
,
longpathW
,
MAX_PATH
);
if
(
!
retW
)
ret
=
0
;
else
if
(
retW
>
MAX_PATH
)
{
SetLastError
(
ERROR_FILENAME_EXCED_RANGE
);
ret
=
0
;
}
else
{
ret
=
strlen
(
full_name
.
short_name
);
if
(
longlen
>
0
&&
!
MultiByteToWideChar
(
CP_ACP
,
0
,
full_name
.
long_name
,
-
1
,
longpath
,
longlen
))
longpath
[
longlen
-
1
]
=
0
;
ret
=
WideCharToMultiByte
(
CP_ACP
,
0
,
longpathW
,
-
1
,
NULL
,
0
,
NULL
,
NULL
);
if
(
ret
<=
longlen
)
{
WideCharToMultiByte
(
CP_ACP
,
0
,
longpathW
,
-
1
,
longpath
,
longlen
,
NULL
,
NULL
);
ret
--
;
/* length without 0 */
}
}
HeapFree
(
GetProcessHeap
(),
0
,
shortpathA
);
RtlFreeUnicodeString
(
&
shortpathW
);
return
ret
;
}
...
...
@@ -1248,20 +1420,29 @@ DWORD WINAPI GetLongPathNameW( LPCWSTR shortpath, LPWSTR longpath,
* A test for GetFullPathName with many pathological cases
* now gives identical output for Wine and OSR2
*/
static
DWORD
DOSFS_DoGetFullPathName
(
LPCSTR
name
,
DWORD
len
,
LPSTR
result
,
BOOL
unicode
)
static
DWORD
DOSFS_DoGetFullPathName
(
LPCWSTR
name
,
DWORD
len
,
LPWSTR
result
)
{
DWORD
ret
;
DOS_FULL_NAME
full_name
;
char
*
p
,
*
q
;
LPWSTR
p
,
q
;
char
*
p_l
;
const
char
*
root
;
char
drivecur
[]
=
"c:."
;
char
driveletter
=
0
;
WCHAR
drivecur
[]
=
{
'C'
,
':'
,
'.'
,
0
}
;
WCHAR
driveletter
=
0
;
int
namelen
,
drive
=
0
;
static
const
WCHAR
bkslashW
[]
=
{
'\\'
,
0
};
static
const
WCHAR
dotW
[]
=
{
'.'
,
0
};
static
const
WCHAR
updir_slashW
[]
=
{
'\\'
,
'.'
,
'.'
,
'\\'
,
0
};
static
const
WCHAR
curdirW
[]
=
{
'\\'
,
'.'
,
'\\'
,
0
};
static
const
WCHAR
updirW
[]
=
{
'\\'
,
'.'
,
'.'
,
0
};
if
(
!
name
[
0
])
return
0
;
if
(
!
name
[
0
])
{
SetLastError
(
ERROR_BAD_PATHNAME
);
return
0
;
}
TRACE
(
"passed
'%s'
\n
"
,
name
);
TRACE
(
"passed
%s
\n
"
,
debugstr_w
(
name
)
);
if
(
name
[
1
]
==
':'
)
/*drive letter given */
...
...
@@ -1271,17 +1452,18 @@ static DWORD DOSFS_DoGetFullPathName( LPCSTR name, DWORD len, LPSTR result,
if
((
name
[
1
]
==
':'
)
&&
((
name
[
2
]
==
'\\'
)
||
(
name
[
2
]
==
'/'
)))
/*absolute path given */
{
lstrcpynA
(
full_name
.
short_name
,
name
,
MAX_PATHNAME_LEN
);
drive
=
(
int
)
FILE_toupper
(
name
[
0
])
-
'A'
;
strncpyW
(
full_name
.
short_name
,
name
,
MAX_PATHNAME_LEN
);
full_name
.
short_name
[
MAX_PATHNAME_LEN
-
1
]
=
0
;
/* ensure 0 termination */
drive
=
toupperW
(
name
[
0
])
-
'A'
;
}
else
{
if
(
driveletter
)
drivecur
[
0
]
=
driveletter
;
else
if
((
name
[
0
]
==
'\\'
)
||
(
name
[
0
]
==
'/'
))
strcpy
(
drivecur
,
"
\\
"
);
strcpy
W
(
drivecur
,
bkslashW
);
else
strcpy
(
drivecur
,
"."
);
strcpy
W
(
drivecur
,
dotW
);
if
(
!
DOSFS_GetFullName
(
drivecur
,
FALSE
,
&
full_name
))
{
...
...
@@ -1289,7 +1471,7 @@ static DWORD DOSFS_DoGetFullPathName( LPCSTR name, DWORD len, LPSTR result,
return
0
;
}
/* find path that drive letter substitutes*/
drive
=
(
int
)
FILE_toupper
(
full_name
.
short_name
[
0
])
-
0x41
;
drive
=
toupperW
(
full_name
.
short_name
[
0
])
-
'A'
;
root
=
DRIVE_GetRoot
(
drive
);
if
(
!
root
)
{
...
...
@@ -1299,31 +1481,33 @@ static DWORD DOSFS_DoGetFullPathName( LPCSTR name, DWORD len, LPSTR result,
if
(
!
strcmp
(
root
,
"/"
))
{
/* we have just the last / and we need it. */
p
=
full_name
.
long_name
;
p
_l
=
full_name
.
long_name
;
}
else
{
p
=
full_name
.
long_name
+
strlen
(
root
);
p
_l
=
full_name
.
long_name
+
strlen
(
root
);
}
/* append long name (= unix name) to drive */
lstrcpynA
(
full_name
.
short_name
+
2
,
p
,
MAX_PATHNAME_LEN
-
3
);
MultiByteToWideChar
(
DRIVE_GetCodepage
(
drive
),
0
,
p_l
,
-
1
,
full_name
.
short_name
+
2
,
MAX_PATHNAME_LEN
-
3
);
/* append name to treat */
namelen
=
strlen
(
full_name
.
short_name
);
p
=
(
char
*
)
name
;
namelen
=
strlen
W
(
full_name
.
short_name
);
p
=
(
LPWSTR
)
name
;
if
(
driveletter
)
p
+=
+
2
;
/* skip drive name when appending */
if
(
namelen
+
2
+
strlen
(
p
)
>
MAX_PATHNAME_LEN
)
p
+=
2
;
/* skip drive name when appending */
if
(
namelen
+
2
+
strlenW
(
p
)
>
MAX_PATHNAME_LEN
)
{
FIXME
(
"internal error: buffer too small
\n
"
);
return
0
;
}
full_name
.
short_name
[
namelen
++
]
=
'\\'
;
full_name
.
short_name
[
namelen
]
=
0
;
lstrcpynA
(
full_name
.
short_name
+
namelen
,
p
,
MAX_PATHNAME_LEN
-
namelen
);
strncpyW
(
full_name
.
short_name
+
namelen
,
p
,
MAX_PATHNAME_LEN
-
namelen
);
full_name
.
short_name
[
MAX_PATHNAME_LEN
-
1
]
=
0
;
/* ensure 0 termination */
}
/* reverse all slashes */
for
(
p
=
full_name
.
short_name
;
p
<
full_name
.
short_name
+
strlen
(
full_name
.
short_name
);
p
<
full_name
.
short_name
+
strlenW
(
full_name
.
short_name
);
p
++
)
{
if
(
*
p
==
'/'
)
...
...
@@ -1331,40 +1515,40 @@ static DWORD DOSFS_DoGetFullPathName( LPCSTR name, DWORD len, LPSTR result,
}
/* Use memmove, as areas overlap */
/* Delete .. */
while
((
p
=
strstr
(
full_name
.
short_name
,
"
\\
..
\\
"
)))
while
((
p
=
strstr
W
(
full_name
.
short_name
,
updir_slashW
)))
{
if
(
p
>
full_name
.
short_name
+
2
)
{
*
p
=
0
;
q
=
strrchr
(
full_name
.
short_name
,
'\\'
);
memmove
(
q
+
1
,
p
+
4
,
strlen
(
p
+
4
)
+
1
);
q
=
strrchrW
(
full_name
.
short_name
,
'\\'
);
memmove
(
q
+
1
,
p
+
4
,
(
strlenW
(
p
+
4
)
+
1
)
*
sizeof
(
WCHAR
)
);
}
else
{
memmove
(
full_name
.
short_name
+
3
,
p
+
4
,
strlen
(
p
+
4
)
+
1
);
memmove
(
full_name
.
short_name
+
3
,
p
+
4
,
(
strlenW
(
p
+
4
)
+
1
)
*
sizeof
(
WCHAR
)
);
}
}
if
((
full_name
.
short_name
[
2
]
==
'.'
)
&&
(
full_name
.
short_name
[
3
]
==
'.'
))
{
/* This case istn't treated yet : c:..\test */
memmove
(
full_name
.
short_name
+
2
,
full_name
.
short_name
+
4
,
strlen
(
full_name
.
short_name
+
4
)
+
1
);
(
strlenW
(
full_name
.
short_name
+
4
)
+
1
)
*
sizeof
(
WCHAR
)
);
}
/* Delete . */
while
((
p
=
strstr
(
full_name
.
short_name
,
"
\\
.
\\
"
)))
while
((
p
=
strstr
W
(
full_name
.
short_name
,
curdirW
)))
{
*
(
p
+
1
)
=
0
;
memmove
(
p
+
1
,
p
+
3
,
strlen
(
p
+
3
)
+
1
);
memmove
(
p
+
1
,
p
+
3
,
(
strlenW
(
p
+
3
)
+
1
)
*
sizeof
(
WCHAR
)
);
}
if
(
!
(
DRIVE_GetFlags
(
drive
)
&
DRIVE_CASE_PRESERVING
))
for
(
p
=
full_name
.
short_name
;
*
p
;
p
++
)
*
p
=
FILE_toupper
(
*
p
);
namelen
=
strlen
(
full_name
.
short_name
);
if
(
!
strcmp
(
full_name
.
short_name
+
namelen
-
3
,
"
\\
.."
))
for
(
p
=
full_name
.
short_name
;
*
p
;
p
++
)
*
p
=
toupperW
(
*
p
);
namelen
=
strlenW
(
full_name
.
short_name
);
if
(
!
strcmp
W
(
full_name
.
short_name
+
namelen
-
3
,
updirW
))
{
/* one more strange case: "c:\test\test1\.."
return "c:\test" */
*
(
full_name
.
short_name
+
namelen
-
3
)
=
0
;
q
=
strrchr
(
full_name
.
short_name
,
'\\'
);
q
=
strrchrW
(
full_name
.
short_name
,
'\\'
);
*
q
=
0
;
}
if
(
full_name
.
short_name
[
namelen
-
1
]
==
'.'
)
...
...
@@ -1372,13 +1556,13 @@ static DWORD DOSFS_DoGetFullPathName( LPCSTR name, DWORD len, LPSTR result,
if
(
!
driveletter
)
if
(
full_name
.
short_name
[
namelen
-
1
]
==
'\\'
)
full_name
.
short_name
[(
namelen
--
)
-
1
]
=
0
;
TRACE
(
"got %s
\n
"
,
full_name
.
short_name
);
TRACE
(
"got %s
\n
"
,
debugstr_w
(
full_name
.
short_name
)
);
/* If the lpBuffer buffer is too small, the return value is the
size of the buffer, in characters, required to hold the path
plus the terminating \0 (tested against win95osr2, bon 001118)
. */
ret
=
strlen
(
full_name
.
short_name
);
ret
=
strlen
W
(
full_name
.
short_name
);
if
(
ret
>=
len
)
{
/* don't touch anything when the buffer is not large enough */
...
...
@@ -1387,13 +1571,11 @@ static DWORD DOSFS_DoGetFullPathName( LPCSTR name, DWORD len, LPSTR result,
}
if
(
result
)
{
if
(
unicode
)
MultiByteToWideChar
(
CP_ACP
,
0
,
full_name
.
short_name
,
-
1
,
(
LPWSTR
)
result
,
len
);
else
lstrcpynA
(
result
,
full_name
.
short_name
,
len
);
strncpyW
(
result
,
full_name
.
short_name
,
len
);
result
[
len
-
1
]
=
0
;
/* ensure 0 termination */
}
TRACE
(
"returning
'%s'
\n
"
,
full_name
.
short_name
);
TRACE
(
"returning
%s
\n
"
,
debugstr_w
(
full_name
.
short_name
)
);
return
ret
;
}
...
...
@@ -1406,18 +1588,54 @@ static DWORD DOSFS_DoGetFullPathName( LPCSTR name, DWORD len, LPSTR result,
DWORD
WINAPI
GetFullPathNameA
(
LPCSTR
name
,
DWORD
len
,
LPSTR
buffer
,
LPSTR
*
lastpart
)
{
DWORD
ret
=
DOSFS_DoGetFullPathName
(
name
,
len
,
buffer
,
FALSE
);
if
(
ret
&&
(
ret
<=
len
)
&&
buffer
&&
lastpart
)
UNICODE_STRING
nameW
;
WCHAR
bufferW
[
MAX_PATH
];
DWORD
ret
,
retW
;
if
(
!
name
)
{
LPSTR
p
=
buffer
+
strlen
(
buffer
);
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
0
;
}
if
(
*
p
!=
'\\'
)
if
(
!
RtlCreateUnicodeStringFromAsciiz
(
&
nameW
,
name
))
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
0
;
}
retW
=
GetFullPathNameW
(
nameW
.
Buffer
,
MAX_PATH
,
bufferW
,
NULL
);
if
(
!
retW
)
ret
=
0
;
else
if
(
retW
>
MAX_PATH
)
{
SetLastError
(
ERROR_FILENAME_EXCED_RANGE
);
ret
=
0
;
}
else
{
ret
=
WideCharToMultiByte
(
CP_ACP
,
0
,
bufferW
,
-
1
,
NULL
,
0
,
NULL
,
NULL
);
if
(
ret
<=
len
)
{
while
((
p
>
buffer
+
2
)
&&
(
*
p
!=
'\\'
))
p
--
;
*
lastpart
=
p
+
1
;
}
else
*
lastpart
=
NULL
;
WideCharToMultiByte
(
CP_ACP
,
0
,
bufferW
,
-
1
,
buffer
,
len
,
NULL
,
NULL
);
ret
--
;
/* length without 0 */
if
(
lastpart
)
{
LPSTR
p
=
buffer
+
strlen
(
buffer
);
if
(
*
p
!=
'\\'
)
{
while
((
p
>
buffer
+
2
)
&&
(
*
p
!=
'\\'
))
p
--
;
*
lastpart
=
p
+
1
;
}
else
*
lastpart
=
NULL
;
}
}
}
RtlFreeUnicodeString
(
&
nameW
);
return
ret
;
}
...
...
@@ -1428,9 +1646,7 @@ DWORD WINAPI GetFullPathNameA( LPCSTR name, DWORD len, LPSTR buffer,
DWORD
WINAPI
GetFullPathNameW
(
LPCWSTR
name
,
DWORD
len
,
LPWSTR
buffer
,
LPWSTR
*
lastpart
)
{
LPSTR
nameA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
name
);
DWORD
ret
=
DOSFS_DoGetFullPathName
(
nameA
,
len
,
(
LPSTR
)
buffer
,
TRUE
);
HeapFree
(
GetProcessHeap
(),
0
,
nameA
);
DWORD
ret
=
DOSFS_DoGetFullPathName
(
name
,
len
,
buffer
);
if
(
ret
&&
(
ret
<=
len
)
&&
buffer
&&
lastpart
)
{
LPWSTR
p
=
buffer
+
strlenW
(
buffer
);
...
...
@@ -1449,12 +1665,21 @@ DWORD WINAPI GetFullPathNameW( LPCWSTR name, DWORD len, LPWSTR buffer,
* wine_get_unix_file_name (KERNEL32.@) Not a Windows API
*
* Return the full Unix file name for a given path.
* FIXME: convert dos file name to unicode
*/
BOOL
WINAPI
wine_get_unix_file_name
(
LPCSTR
dos
,
LPSTR
buffer
,
DWORD
len
)
{
BOOL
ret
;
DOS_FULL_NAME
path
;
if
((
ret
=
DOSFS_GetFullName
(
dos
,
FALSE
,
&
path
)))
lstrcpynA
(
buffer
,
path
.
long_name
,
len
);
WCHAR
dosW
[
MAX_PATHNAME_LEN
];
MultiByteToWideChar
(
CP_ACP
,
0
,
dos
,
-
1
,
dosW
,
MAX_PATHNAME_LEN
);
ret
=
DOSFS_GetFullName
(
dosW
,
FALSE
,
&
path
);
if
(
ret
&&
len
)
{
strncpy
(
buffer
,
path
.
long_name
,
len
);
buffer
[
len
-
1
]
=
0
;
/* ensure 0 termination */
}
return
ret
;
}
...
...
@@ -1462,16 +1687,16 @@ BOOL WINAPI wine_get_unix_file_name( LPCSTR dos, LPSTR buffer, DWORD len )
/***********************************************************************
* DOSFS_FindNextEx
*/
static
int
DOSFS_FindNextEx
(
FIND_FIRST_INFO
*
info
,
WIN32_FIND_DATA
A
*
entry
)
static
int
DOSFS_FindNextEx
(
FIND_FIRST_INFO
*
info
,
WIN32_FIND_DATA
W
*
entry
)
{
DWORD
attr
=
info
->
attr
|
FA_UNUSED
|
FA_ARCHIVE
|
FA_RDONLY
|
FILE_ATTRIBUTE_SYMLINK
;
UINT
flags
=
DRIVE_GetFlags
(
info
->
drive
);
char
*
p
,
buffer
[
MAX_PATHNAME_LEN
];
const
char
*
drive_path
;
int
drive_root
;
LPCSTR
long_name
,
short_name
;
LPC
W
STR
long_name
,
short_name
;
BY_HANDLE_FILE_INFORMATION
fileinfo
;
char
dos_name
[
13
];
WCHAR
dos_name
[
13
];
if
((
info
->
attr
&
~
(
FA_UNUSED
|
FA_ARCHIVE
|
FA_RDONLY
))
==
FA_LABEL
)
{
...
...
@@ -1485,10 +1710,10 @@ static int DOSFS_FindNextEx( FIND_FIRST_INFO *info, WIN32_FIND_DATAA *entry )
entry
->
dwReserved0
=
0
;
entry
->
dwReserved1
=
0
;
DOSFS_ToDosDTAFormat
(
DRIVE_GetLabel
(
info
->
drive
),
entry
->
cFileName
);
strcpy
(
entry
->
cAlternateFileName
,
entry
->
cFileName
);
strcpy
W
(
entry
->
cAlternateFileName
,
entry
->
cFileName
);
info
->
cur_pos
++
;
TRACE
(
"returning %s (%s) as label
\n
"
,
entry
->
cFileName
,
entry
->
cAlternateFileName
);
debugstr_w
(
entry
->
cFileName
),
debugstr_w
(
entry
->
cAlternateFileName
)
);
return
1
;
}
...
...
@@ -1531,8 +1756,8 @@ static int DOSFS_FindNextEx( FIND_FIRST_INFO *info, WIN32_FIND_DATAA *entry )
}
/* Check the file attributes */
lstrcpynA
(
p
,
long_name
,
sizeof
(
buffer
)
-
(
int
)(
p
-
buffer
)
);
WideCharToMultiByte
(
DRIVE_GetCodepage
(
info
->
drive
),
0
,
long_name
,
-
1
,
p
,
sizeof
(
buffer
)
-
(
int
)(
p
-
buffer
),
NULL
,
NULL
);
if
(
!
FILE_Stat
(
buffer
,
&
fileinfo
))
{
WARN
(
"can't stat %s
\n
"
,
buffer
);
...
...
@@ -1541,9 +1766,11 @@ static int DOSFS_FindNextEx( FIND_FIRST_INFO *info, WIN32_FIND_DATAA *entry )
if
((
fileinfo
.
dwFileAttributes
&
FILE_ATTRIBUTE_SYMLINK
)
&&
(
fileinfo
.
dwFileAttributes
&
FILE_ATTRIBUTE_DIRECTORY
))
{
static
const
WCHAR
wineW
[]
=
{
'w'
,
'i'
,
'n'
,
'e'
,
0
};
static
const
WCHAR
ShowDirSymlinksW
[]
=
{
'S'
,
'h'
,
'o'
,
'w'
,
'D'
,
'i'
,
'r'
,
'S'
,
'y'
,
'm'
,
'l'
,
'i'
,
'n'
,
'k'
,
's'
,
0
};
static
int
show_dir_symlinks
=
-
1
;
if
(
show_dir_symlinks
==
-
1
)
show_dir_symlinks
=
PROFILE_GetWineIniBool
(
"wine"
,
"ShowDirSymlinks"
,
0
);
show_dir_symlinks
=
PROFILE_GetWineIniBool
(
wineW
,
ShowDirSymlinksW
,
0
);
if
(
!
show_dir_symlinks
)
continue
;
}
...
...
@@ -1564,10 +1791,10 @@ static int DOSFS_FindNextEx( FIND_FIRST_INFO *info, WIN32_FIND_DATAA *entry )
DOSFS_Hash
(
long_name
,
entry
->
cAlternateFileName
,
FALSE
,
!
(
flags
&
DRIVE_CASE_SENSITIVE
)
);
lstrcpyn
A
(
entry
->
cFileName
,
long_name
,
sizeof
(
entry
->
cFileName
)
);
if
(
!
(
flags
&
DRIVE_CASE_PRESERVING
))
_strlwr
(
entry
->
cFileName
);
lstrcpyn
W
(
entry
->
cFileName
,
long_name
,
sizeof
(
entry
->
cFileName
)
/
sizeof
(
entry
->
cFileName
[
0
]
)
);
if
(
!
(
flags
&
DRIVE_CASE_PRESERVING
))
strlwrW
(
entry
->
cFileName
);
TRACE
(
"returning %s (%s) %02lx %ld
\n
"
,
entry
->
cFileName
,
entry
->
cAlternateFileName
,
debugstr_w
(
entry
->
cFileName
),
debugstr_w
(
entry
->
cAlternateFileName
)
,
entry
->
dwFileAttributes
,
entry
->
nFileSizeLow
);
return
1
;
}
...
...
@@ -1592,26 +1819,38 @@ int DOSFS_FindNext( const char *path, const char *short_mask,
int
skip
,
WIN32_FIND_DATAA
*
entry
)
{
static
FIND_FIRST_INFO
info
;
LPCSTR
short_name
,
long_name
;
LPC
W
STR
short_name
,
long_name
;
int
count
;
UNICODE_STRING
short_maskW
,
long_maskW
;
WIN32_FIND_DATAW
entryW
;
_EnterWin16Lock
();
RtlCreateUnicodeStringFromAsciiz
(
&
short_maskW
,
short_mask
);
RtlCreateUnicodeStringFromAsciiz
(
&
long_maskW
,
long_mask
);
/* Check the cached directory */
if
(
!
(
info
.
u
.
dos_dir
&&
info
.
path
==
path
&&
info
.
short_mask
==
short_mask
&&
info
.
long_mask
==
long_mask
&&
info
.
drive
==
drive
if
(
!
(
info
.
u
.
dos_dir
&&
info
.
path
==
path
&&
!
strcmpW
(
info
.
short_mask
,
short_maskW
.
Buffer
)
&&
!
strcmpW
(
info
.
long_mask
,
long_maskW
.
Buffer
)
&&
info
.
drive
==
drive
&&
info
.
attr
==
attr
&&
info
.
cur_pos
<=
skip
))
{
/* Not in the cache, open it anew */
if
(
info
.
u
.
dos_dir
)
DOSFS_CloseDir
(
info
.
u
.
dos_dir
);
info
.
path
=
(
LPSTR
)
path
;
info
.
long_mask
=
(
LPSTR
)
long_mask
;
info
.
short_mask
=
(
LPSTR
)
short_mask
;
RtlFreeHeap
(
GetProcessHeap
(),
0
,
info
.
long_mask
);
RtlFreeHeap
(
GetProcessHeap
(),
0
,
info
.
short_mask
);
info
.
long_mask
=
long_maskW
.
Buffer
;
info
.
short_mask
=
short_maskW
.
Buffer
;
info
.
attr
=
attr
;
info
.
drive
=
drive
;
info
.
cur_pos
=
0
;
info
.
u
.
dos_dir
=
DOSFS_OpenDir
(
info
.
path
);
info
.
u
.
dos_dir
=
DOSFS_OpenDir
(
DRIVE_GetCodepage
(
drive
),
info
.
path
);
}
else
{
RtlFreeUnicodeString
(
&
short_maskW
);
RtlFreeUnicodeString
(
&
long_maskW
);
}
/* Skip to desired position */
...
...
@@ -1621,8 +1860,14 @@ int DOSFS_FindNext( const char *path, const char *short_mask,
else
break
;
if
(
info
.
u
.
dos_dir
&&
info
.
cur_pos
==
skip
&&
DOSFS_FindNextEx
(
&
info
,
entry
))
if
(
info
.
u
.
dos_dir
&&
info
.
cur_pos
==
skip
&&
DOSFS_FindNextEx
(
&
info
,
&
entryW
))
{
WideCharToMultiByte
(
CP_ACP
,
0
,
entryW
.
cFileName
,
-
1
,
entry
->
cFileName
,
sizeof
(
entry
->
cFileName
),
NULL
,
NULL
);
WideCharToMultiByte
(
CP_ACP
,
0
,
entryW
.
cAlternateFileName
,
-
1
,
entry
->
cAlternateFileName
,
sizeof
(
entry
->
cAlternateFileName
),
NULL
,
NULL
);
count
=
info
.
cur_pos
-
skip
;
}
else
count
=
0
;
...
...
@@ -1638,10 +1883,10 @@ int DOSFS_FindNext( const char *path, const char *short_mask,
}
/*************************************************************************
* FindFirstFileEx
A
(KERNEL32.@)
* FindFirstFileEx
W
(KERNEL32.@)
*/
HANDLE
WINAPI
FindFirstFileEx
A
(
LPCSTR
lpFileName
,
HANDLE
WINAPI
FindFirstFileEx
W
(
LPC
W
STR
lpFileName
,
FINDEX_INFO_LEVELS
fInfoLevelId
,
LPVOID
lpFindFileData
,
FINDEX_SEARCH_OPS
fSearchOp
,
...
...
@@ -1651,6 +1896,12 @@ HANDLE WINAPI FindFirstFileExA(
HGLOBAL
handle
;
FIND_FIRST_INFO
*
info
;
if
(
!
lpFileName
)
{
SetLastError
(
ERROR_PATH_NOT_FOUND
);
return
INVALID_HANDLE_VALUE
;
}
if
((
fSearchOp
!=
FindExSearchNameMatch
)
||
(
dwAdditionalFlags
!=
0
))
{
FIXME
(
"options not implemented 0x%08x 0x%08lx
\n
"
,
fSearchOp
,
dwAdditionalFlags
);
...
...
@@ -1661,7 +1912,11 @@ HANDLE WINAPI FindFirstFileExA(
{
case
FindExInfoStandard
:
{
WIN32_FIND_DATAA
*
data
=
(
WIN32_FIND_DATAA
*
)
lpFindFileData
;
WIN32_FIND_DATAW
*
data
=
(
WIN32_FIND_DATAW
*
)
lpFindFileData
;
char
*
p
;
INT
long_mask_len
;
UINT
codepage
;
data
->
dwReserved0
=
data
->
dwReserved1
=
0x0
;
if
(
!
lpFileName
)
return
0
;
if
(
lpFileName
[
0
]
==
'\\'
&&
lpFileName
[
1
]
==
'\\'
)
...
...
@@ -1686,25 +1941,28 @@ HANDLE WINAPI FindFirstFileExA(
{
DOS_FULL_NAME
full_name
;
if
(
!
DOSFS_GetFullName
(
lpFileName
,
FALSE
,
&
full_name
))
break
;
if
(
!
(
handle
=
GlobalAlloc
(
GMEM_MOVEABLE
,
sizeof
(
FIND_FIRST_INFO
))))
break
;
info
=
(
FIND_FIRST_INFO
*
)
GlobalLock
(
handle
);
info
->
path
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlen
(
full_name
.
long_name
)
+
1
);
strcpy
(
info
->
path
,
full_name
.
long_name
);
info
->
long_mask
=
strrchr
(
info
->
path
,
'/'
);
*
(
info
->
long_mask
++
)
=
'\0'
;
info
->
short_mask
=
NULL
;
info
->
attr
=
0xff
;
if
(
lpFileName
[
0
]
&&
(
lpFileName
[
1
]
==
':'
))
info
->
drive
=
FILE_toupper
(
*
lpFileName
)
-
'A'
;
else
info
->
drive
=
DRIVE_GetCurrentDrive
();
info
->
cur_pos
=
0
;
info
->
u
.
dos_dir
=
DOSFS_OpenDir
(
info
->
path
);
GlobalUnlock
(
handle
);
if
(
!
DOSFS_GetFullName
(
lpFileName
,
FALSE
,
&
full_name
))
break
;
if
(
!
(
handle
=
GlobalAlloc
(
GMEM_MOVEABLE
,
sizeof
(
FIND_FIRST_INFO
))))
break
;
info
=
(
FIND_FIRST_INFO
*
)
GlobalLock
(
handle
);
info
->
path
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlen
(
full_name
.
long_name
)
+
1
);
strcpy
(
info
->
path
,
full_name
.
long_name
);
codepage
=
DRIVE_GetCodepage
(
full_name
.
drive
);
p
=
strrchr
(
info
->
path
,
'/'
);
*
p
++
=
'\0'
;
long_mask_len
=
MultiByteToWideChar
(
codepage
,
0
,
p
,
-
1
,
NULL
,
0
);
info
->
long_mask
=
HeapAlloc
(
GetProcessHeap
(),
0
,
long_mask_len
*
sizeof
(
WCHAR
)
);
MultiByteToWideChar
(
codepage
,
0
,
p
,
-
1
,
info
->
long_mask
,
long_mask_len
);
info
->
short_mask
=
NULL
;
info
->
attr
=
0xff
;
info
->
drive
=
full_name
.
drive
;
info
->
cur_pos
=
0
;
info
->
u
.
dos_dir
=
DOSFS_OpenDir
(
codepage
,
info
->
path
);
GlobalUnlock
(
handle
);
}
if
(
!
FindNextFileA
(
handle
,
data
))
if
(
!
FindNextFileW
(
handle
,
data
))
{
FindClose
(
handle
);
SetLastError
(
ERROR_NO_MORE_FILES
);
...
...
@@ -1731,10 +1989,10 @@ HANDLE WINAPI FindFirstFileA(
}
/*************************************************************************
* FindFirstFileEx
W
(KERNEL32.@)
* FindFirstFileEx
A
(KERNEL32.@)
*/
HANDLE
WINAPI
FindFirstFileEx
W
(
LPC
W
STR
lpFileName
,
HANDLE
WINAPI
FindFirstFileEx
A
(
LPCSTR
lpFileName
,
FINDEX_INFO_LEVELS
fInfoLevelId
,
LPVOID
lpFindFileData
,
FINDEX_SEARCH_OPS
fSearchOp
,
...
...
@@ -1742,49 +2000,37 @@ HANDLE WINAPI FindFirstFileExW(
DWORD
dwAdditionalFlags
)
{
HANDLE
handle
;
WIN32_FIND_DATAA
dataA
;
LPVOID
_lpFindFileData
;
LPSTR
pathA
;
WIN32_FIND_DATAA
*
dataA
;
WIN32_FIND_DATAW
dataW
;
UNICODE_STRING
pathW
;
switch
(
fInfoLevelId
)
if
(
!
lpFileName
)
{
case
FindExInfoStandard
:
{
_lpFindFileData
=
&
dataA
;
}
break
;
default:
FIXME
(
"fInfoLevelId 0x%08x not implemented
\n
"
,
fInfoLevelId
);
return
INVALID_HANDLE_VALUE
;
SetLastError
(
ERROR_PATH_NOT_FOUND
);
return
INVALID_HANDLE_VALUE
;
}
pathA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
lpFileName
);
handle
=
FindFirstFileExA
(
pathA
,
fInfoLevelId
,
_lpFindFileData
,
fSearchOp
,
lpSearchFilter
,
dwAdditionalFlags
);
HeapFree
(
GetProcessHeap
(),
0
,
pathA
);
if
(
handle
==
INVALID_HANDLE_VALUE
)
return
handle
;
switch
(
fInfoLevelId
)
if
(
!
RtlCreateUnicodeStringFromAsciiz
(
&
pathW
,
lpFileName
))
{
case
FindExInfoStandard
:
{
WIN32_FIND_DATAW
*
dataW
=
(
WIN32_FIND_DATAW
*
)
lpFindFileData
;
dataW
->
dwFileAttributes
=
dataA
.
dwFileAttributes
;
dataW
->
ftCreationTime
=
dataA
.
ftCreationTime
;
dataW
->
ftLastAccessTime
=
dataA
.
ftLastAccessTime
;
dataW
->
ftLastWriteTime
=
dataA
.
ftLastWriteTime
;
dataW
->
nFileSizeHigh
=
dataA
.
nFileSizeHigh
;
dataW
->
nFileSizeLow
=
dataA
.
nFileSizeLow
;
MultiByteToWideChar
(
CP_ACP
,
0
,
dataA
.
cFileName
,
-
1
,
dataW
->
cFileName
,
sizeof
(
dataW
->
cFileName
)
/
sizeof
(
WCHAR
)
);
MultiByteToWideChar
(
CP_ACP
,
0
,
dataA
.
cAlternateFileName
,
-
1
,
dataW
->
cAlternateFileName
,
sizeof
(
dataW
->
cAlternateFileName
)
/
sizeof
(
WCHAR
)
);
}
break
;
default:
FIXME
(
"fInfoLevelId 0x%08x not implemented
\n
"
,
fInfoLevelId
);
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
INVALID_HANDLE_VALUE
;
}
handle
=
FindFirstFileExW
(
pathW
.
Buffer
,
fInfoLevelId
,
&
dataW
,
fSearchOp
,
lpSearchFilter
,
dwAdditionalFlags
);
RtlFreeUnicodeString
(
&
pathW
);
if
(
handle
==
INVALID_HANDLE_VALUE
)
return
handle
;
dataA
=
(
WIN32_FIND_DATAA
*
)
lpFindFileData
;
dataA
->
dwFileAttributes
=
dataW
.
dwFileAttributes
;
dataA
->
ftCreationTime
=
dataW
.
ftCreationTime
;
dataA
->
ftLastAccessTime
=
dataW
.
ftLastAccessTime
;
dataA
->
ftLastWriteTime
=
dataW
.
ftLastWriteTime
;
dataA
->
nFileSizeHigh
=
dataW
.
nFileSizeHigh
;
dataA
->
nFileSizeLow
=
dataW
.
nFileSizeLow
;
WideCharToMultiByte
(
CP_ACP
,
0
,
dataW
.
cFileName
,
-
1
,
dataA
->
cFileName
,
sizeof
(
dataA
->
cFileName
),
NULL
,
NULL
);
WideCharToMultiByte
(
CP_ACP
,
0
,
dataW
.
cAlternateFileName
,
-
1
,
dataA
->
cAlternateFileName
,
sizeof
(
dataA
->
cAlternateFileName
),
NULL
,
NULL
);
return
handle
;
}
...
...
@@ -1798,9 +2044,9 @@ HANDLE WINAPI FindFirstFileW( LPCWSTR lpFileName, WIN32_FIND_DATAW *lpFindData )
}
/*************************************************************************
* FindNextFile
A
(KERNEL32.@)
* FindNextFile
W
(KERNEL32.@)
*/
BOOL
WINAPI
FindNextFile
A
(
HANDLE
handle
,
WIN32_FIND_DATAA
*
data
)
BOOL
WINAPI
FindNextFile
W
(
HANDLE
handle
,
WIN32_FIND_DATAW
*
data
)
{
FIND_FIRST_INFO
*
info
;
BOOL
ret
=
FALSE
;
...
...
@@ -1830,10 +2076,12 @@ BOOL WINAPI FindNextFileA( HANDLE handle, WIN32_FIND_DATAA *data )
{
DOSFS_CloseDir
(
info
->
u
.
dos_dir
);
info
->
u
.
dos_dir
=
NULL
;
HeapFree
(
GetProcessHeap
(),
0
,
info
->
path
);
info
->
path
=
info
->
long_mask
=
NULL
;
info
->
path
=
NULL
;
HeapFree
(
GetProcessHeap
(),
0
,
info
->
long_mask
);
info
->
long_mask
=
NULL
;
goto
done
;
}
else
ret
=
TRUE
;
ret
=
TRUE
;
done:
GlobalUnlock
(
handle
);
if
(
!
ret
)
SetLastError
(
gle
);
...
...
@@ -1842,23 +2090,23 @@ done:
/*************************************************************************
* FindNextFile
W
(KERNEL32.@)
* FindNextFile
A
(KERNEL32.@)
*/
BOOL
WINAPI
FindNextFile
W
(
HANDLE
handle
,
WIN32_FIND_DATAW
*
data
)
BOOL
WINAPI
FindNextFile
A
(
HANDLE
handle
,
WIN32_FIND_DATAA
*
data
)
{
WIN32_FIND_DATA
A
dataA
;
if
(
!
FindNextFile
A
(
handle
,
&
dataA
))
return
FALSE
;
data
->
dwFileAttributes
=
data
A
.
dwFileAttributes
;
data
->
ftCreationTime
=
data
A
.
ftCreationTime
;
data
->
ftLastAccessTime
=
data
A
.
ftLastAccessTime
;
data
->
ftLastWriteTime
=
data
A
.
ftLastWriteTime
;
data
->
nFileSizeHigh
=
data
A
.
nFileSizeHigh
;
data
->
nFileSizeLow
=
data
A
.
nFileSizeLow
;
MultiByteToWideChar
(
CP_ACP
,
0
,
dataA
.
cFileName
,
-
1
,
data
->
cFileName
,
sizeof
(
data
->
cFileName
)
/
sizeof
(
WCHAR
)
);
MultiByteToWideChar
(
CP_ACP
,
0
,
dataA
.
cAlternateFileName
,
-
1
,
WIN32_FIND_DATA
W
dataW
;
if
(
!
FindNextFile
W
(
handle
,
&
dataW
))
return
FALSE
;
data
->
dwFileAttributes
=
data
W
.
dwFileAttributes
;
data
->
ftCreationTime
=
data
W
.
ftCreationTime
;
data
->
ftLastAccessTime
=
data
W
.
ftLastAccessTime
;
data
->
ftLastWriteTime
=
data
W
.
ftLastWriteTime
;
data
->
nFileSizeHigh
=
data
W
.
nFileSizeHigh
;
data
->
nFileSizeLow
=
data
W
.
nFileSizeLow
;
WideCharToMultiByte
(
CP_ACP
,
0
,
dataW
.
cFileName
,
-
1
,
data
->
cFileName
,
sizeof
(
data
->
cFileName
)
,
NULL
,
NULL
);
WideCharToMultiByte
(
CP_ACP
,
0
,
dataW
.
cAlternateFileName
,
-
1
,
data
->
cAlternateFileName
,
sizeof
(
data
->
cAlternateFileName
)
/
sizeof
(
WCHAR
)
);
sizeof
(
data
->
cAlternateFileName
)
,
NULL
,
NULL
);
return
TRUE
;
}
...
...
@@ -1877,6 +2125,7 @@ BOOL WINAPI FindClose( HANDLE handle )
{
if
(
info
->
u
.
dos_dir
)
DOSFS_CloseDir
(
info
->
u
.
dos_dir
);
if
(
info
->
path
)
HeapFree
(
GetProcessHeap
(),
0
,
info
->
path
);
if
(
info
->
long_mask
)
HeapFree
(
GetProcessHeap
(),
0
,
info
->
long_mask
);
}
}
__EXCEPT
(
page_fault
)
...
...
@@ -2399,26 +2648,35 @@ HANDLE16 WINAPI FindFirstFile16( LPCSTR path, WIN32_FIND_DATAA *data )
DOS_FULL_NAME
full_name
;
HGLOBAL16
handle
;
FIND_FIRST_INFO
*
info
;
WCHAR
pathW
[
MAX_PATH
];
char
*
p
;
INT
long_mask_len
;
UINT
codepage
;
data
->
dwReserved0
=
data
->
dwReserved1
=
0x0
;
if
(
!
path
)
return
0
;
if
(
!
DOSFS_GetFullName
(
path
,
FALSE
,
&
full_name
))
if
(
!
path
)
return
INVALID_HANDLE_VALUE16
;
MultiByteToWideChar
(
CP_ACP
,
0
,
path
,
-
1
,
pathW
,
MAX_PATH
);
if
(
!
DOSFS_GetFullName
(
pathW
,
FALSE
,
&
full_name
))
return
INVALID_HANDLE_VALUE16
;
if
(
!
(
handle
=
GlobalAlloc16
(
GMEM_MOVEABLE
,
sizeof
(
FIND_FIRST_INFO
)
)))
return
INVALID_HANDLE_VALUE16
;
info
=
(
FIND_FIRST_INFO
*
)
GlobalLock16
(
handle
);
info
->
path
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlen
(
full_name
.
long_name
)
+
1
);
strcpy
(
info
->
path
,
full_name
.
long_name
);
info
->
long_mask
=
strrchr
(
info
->
path
,
'/'
);
if
(
info
->
long_mask
)
*
(
info
->
long_mask
++
)
=
'\0'
;
codepage
=
DRIVE_GetCodepage
(
full_name
.
drive
);
p
=
strrchr
(
info
->
path
,
'/'
);
*
p
++
=
'\0'
;
long_mask_len
=
MultiByteToWideChar
(
codepage
,
0
,
p
,
-
1
,
NULL
,
0
);
info
->
long_mask
=
HeapAlloc
(
GetProcessHeap
(),
0
,
long_mask_len
*
sizeof
(
WCHAR
)
);
MultiByteToWideChar
(
codepage
,
0
,
p
,
-
1
,
info
->
long_mask
,
long_mask_len
);
info
->
short_mask
=
NULL
;
info
->
attr
=
0xff
;
if
(
path
[
0
]
&&
(
path
[
1
]
==
':'
))
info
->
drive
=
FILE_toupper
(
*
path
)
-
'A'
;
else
info
->
drive
=
DRIVE_GetCurrentDrive
();
info
->
drive
=
full_name
.
drive
;
info
->
cur_pos
=
0
;
info
->
u
.
dos_dir
=
DOSFS_OpenDir
(
info
->
path
);
info
->
u
.
dos_dir
=
DOSFS_OpenDir
(
codepage
,
info
->
path
);
GlobalUnlock16
(
handle
);
if
(
!
FindNextFile16
(
handle
,
data
))
...
...
@@ -2436,28 +2694,48 @@ HANDLE16 WINAPI FindFirstFile16( LPCSTR path, WIN32_FIND_DATAA *data )
BOOL16
WINAPI
FindNextFile16
(
HANDLE16
handle
,
WIN32_FIND_DATAA
*
data
)
{
FIND_FIRST_INFO
*
info
;
WIN32_FIND_DATAW
dataW
;
BOOL
ret
=
FALSE
;
DWORD
gle
=
ERROR_NO_MORE_FILES
;
if
((
handle
==
INVALID_HANDLE_VALUE16
)
||
!
(
info
=
(
FIND_FIRST_INFO
*
)
GlobalLock16
(
handle
)))
{
SetLastError
(
ERROR_INVALID_HANDLE
);
return
FALSE
;
return
ret
;
}
GlobalUnlock16
(
handle
);
if
(
!
info
->
path
||
!
info
->
u
.
dos_dir
)
{
SetLastError
(
ERROR_NO_MORE_FILES
);
return
FALSE
;
goto
done
;
}
if
(
!
DOSFS_FindNextEx
(
info
,
data
))
if
(
!
DOSFS_FindNextEx
(
info
,
&
dataW
))
{
DOSFS_CloseDir
(
info
->
u
.
dos_dir
);
info
->
u
.
dos_dir
=
NULL
;
HeapFree
(
GetProcessHeap
(),
0
,
info
->
path
);
info
->
path
=
info
->
long_mask
=
NULL
;
SetLastError
(
ERROR_NO_MORE_FILES
);
return
FALSE
;
info
->
path
=
NULL
;
HeapFree
(
GetProcessHeap
(),
0
,
info
->
long_mask
);
info
->
long_mask
=
NULL
;
goto
done
;
}
return
TRUE
;
ret
=
TRUE
;
data
->
dwFileAttributes
=
dataW
.
dwFileAttributes
;
data
->
ftCreationTime
=
dataW
.
ftCreationTime
;
data
->
ftLastAccessTime
=
dataW
.
ftLastAccessTime
;
data
->
ftLastWriteTime
=
dataW
.
ftLastWriteTime
;
data
->
nFileSizeHigh
=
dataW
.
nFileSizeHigh
;
data
->
nFileSizeLow
=
dataW
.
nFileSizeLow
;
WideCharToMultiByte
(
CP_ACP
,
0
,
dataW
.
cFileName
,
-
1
,
data
->
cFileName
,
sizeof
(
data
->
cFileName
),
NULL
,
NULL
);
WideCharToMultiByte
(
CP_ACP
,
0
,
dataW
.
cAlternateFileName
,
-
1
,
data
->
cAlternateFileName
,
sizeof
(
data
->
cAlternateFileName
),
NULL
,
NULL
);
done:
if
(
!
ret
)
SetLastError
(
gle
);
GlobalUnlock16
(
handle
);
return
ret
;
}
/*************************************************************************
...
...
@@ -2475,6 +2753,7 @@ BOOL16 WINAPI FindClose16( HANDLE16 handle )
}
if
(
info
->
u
.
dos_dir
)
DOSFS_CloseDir
(
info
->
u
.
dos_dir
);
if
(
info
->
path
)
HeapFree
(
GetProcessHeap
(),
0
,
info
->
path
);
if
(
info
->
long_mask
)
HeapFree
(
GetProcessHeap
(),
0
,
info
->
long_mask
);
GlobalUnlock16
(
handle
);
GlobalFree16
(
handle
);
return
TRUE
;
...
...
files/drive.c
View file @
d75aed2c
...
...
@@ -66,6 +66,7 @@
#include "heap.h"
#include "msdos.h"
#include "task.h"
#include "wine/unicode.h"
#include "wine/library.h"
#include "wine/server.h"
#include "wine/debug.h"
...
...
@@ -76,28 +77,29 @@ WINE_DECLARE_DEBUG_CHANNEL(file);
typedef
struct
{
char
*
root
;
/* root dir in Unix format without trailing / */
char
*
dos_cwd
;
/* cwd in DOS format without leading or trailing \ */
LPWSTR
dos_cwd
;
/* cwd in DOS format without leading or trailing \ */
char
*
unix_cwd
;
/* cwd in Unix format without leading or trailing / */
char
*
device
;
/* raw device path */
char
label_conf
[
12
];
/* drive label as cfg'd in wine config */
char
label_read
[
12
];
/* drive label as read from device */
WCHAR
label_conf
[
12
];
/* drive label as cfg'd in wine config */
WCHAR
label_read
[
12
];
/* drive label as read from device */
DWORD
serial_conf
;
/* drive serial number as cfg'd in wine config */
UINT
type
;
/* drive type */
UINT
flags
;
/* drive flags */
UINT
codepage
;
/* drive code page */
dev_t
dev
;
/* unix device number */
ino_t
ino
;
/* unix inode number */
}
DOSDRIVE
;
static
const
char
*
const
DRIVE_Types
[
]
=
static
const
WCHAR
DRIVE_Types
[][
8
]
=
{
""
,
/* DRIVE_UNKNOWN */
""
,
/* DRIVE_NO_ROOT_DIR */
"floppy"
,
/* DRIVE_REMOVABLE */
"hd"
,
/* DRIVE_FIXED */
"network"
,
/* DRIVE_REMOTE */
"cdrom"
,
/* DRIVE_CDROM */
"ramdisk"
/* DRIVE_RAMDISK */
{
0
},
/* DRIVE_UNKNOWN */
{
0
},
/* DRIVE_NO_ROOT_DIR */
{
'f'
,
'l'
,
'o'
,
'p'
,
'p'
,
'y'
,
0
},
/* DRIVE_REMOVABLE */
{
'h'
,
'd'
,
0
},
/* DRIVE_FIXED */
{
'n'
,
'e'
,
't'
,
'w'
,
'o'
,
'r'
,
'k'
,
0
},
/* DRIVE_REMOTE */
{
'c'
,
'd'
,
'r'
,
'o'
,
'm'
,
0
},
/* DRIVE_CDROM */
{
'r'
,
'a'
,
'm'
,
'd'
,
'i'
,
's'
,
'k'
,
0
}
/* DRIVE_RAMDISK */
};
...
...
@@ -105,19 +107,19 @@ static const char * const DRIVE_Types[] =
typedef
struct
{
const
char
*
name
;
const
WCHAR
name
[
6
]
;
UINT
flags
;
}
FS_DESCR
;
static
const
FS_DESCR
DRIVE_Filesystems
[]
=
{
{
"unix"
,
DRIVE_CASE_SENSITIVE
|
DRIVE_CASE_PRESERVING
},
{
"msdos"
,
DRIVE_SHORT_NAMES
},
{
"dos"
,
DRIVE_SHORT_NAMES
},
{
"fat"
,
DRIVE_SHORT_NAMES
},
{
"vfat"
,
DRIVE_CASE_PRESERVING
},
{
"win95"
,
DRIVE_CASE_PRESERVING
},
{
NULL
,
0
}
{
{
'u'
,
'n'
,
'i'
,
'x'
,
0
},
DRIVE_CASE_SENSITIVE
|
DRIVE_CASE_PRESERVING
},
{
{
'm'
,
's'
,
'd'
,
'o'
,
's'
,
0
},
DRIVE_SHORT_NAMES
},
{
{
'd'
,
'o'
,
's'
,
0
},
DRIVE_SHORT_NAMES
},
{
{
'f'
,
'a'
,
't'
,
0
},
DRIVE_SHORT_NAMES
},
{
{
'v'
,
'f'
,
'a'
,
't'
,
0
},
DRIVE_CASE_PRESERVING
},
{
{
'w'
,
'i'
,
'n'
,
'9'
,
'5'
,
0
},
DRIVE_CASE_PRESERVING
},
{
{
0
}
,
0
}
};
...
...
@@ -140,18 +142,22 @@ extern void CDROM_InitRegistry(int dev);
/***********************************************************************
* DRIVE_GetDriveType
*/
static
UINT
DRIVE_GetDriveType
(
const
char
*
name
)
static
UINT
DRIVE_GetDriveType
(
LPCWSTR
name
)
{
char
buffer
[
20
];
WCHAR
buffer
[
20
];
int
i
;
static
const
WCHAR
TypeW
[]
=
{
'T'
,
'y'
,
'p'
,
'e'
,
0
};
static
const
WCHAR
hdW
[]
=
{
'h'
,
'd'
,
0
};
PROFILE_GetWineIniString
(
name
,
"Type"
,
"hd"
,
buffer
,
sizeof
(
buffer
)
);
PROFILE_GetWineIniString
(
name
,
TypeW
,
hdW
,
buffer
,
20
);
if
(
!
buffer
[
0
])
strcpyW
(
buffer
,
hdW
);
for
(
i
=
0
;
i
<
sizeof
(
DRIVE_Types
)
/
sizeof
(
DRIVE_Types
[
0
]);
i
++
)
{
if
(
!
strc
asecmp
(
buffer
,
DRIVE_Types
[
i
]
))
return
i
;
if
(
!
strc
mpiW
(
buffer
,
DRIVE_Types
[
i
]
))
return
i
;
}
MESSAGE
(
"%s: unknown drive type
'%s'
, defaulting to 'hd'.
\n
"
,
name
,
buffer
);
MESSAGE
(
"%s: unknown drive type
%s
, defaulting to 'hd'.
\n
"
,
debugstr_w
(
name
),
debugstr_w
(
buffer
)
);
return
DRIVE_FIXED
;
}
...
...
@@ -159,14 +165,14 @@ static UINT DRIVE_GetDriveType( const char *name )
/***********************************************************************
* DRIVE_GetFSFlags
*/
static
UINT
DRIVE_GetFSFlags
(
const
char
*
name
,
const
char
*
value
)
static
UINT
DRIVE_GetFSFlags
(
LPCWSTR
name
,
LPCWSTR
value
)
{
const
FS_DESCR
*
descr
;
for
(
descr
=
DRIVE_Filesystems
;
descr
->
name
;
descr
++
)
if
(
!
strc
asecmp
(
value
,
descr
->
name
))
return
descr
->
flags
;
MESSAGE
(
"%s: unknown filesystem type
'%s'
, defaulting to 'win95'.
\n
"
,
name
,
value
);
for
(
descr
=
DRIVE_Filesystems
;
*
descr
->
name
;
descr
++
)
if
(
!
strc
mpiW
(
value
,
descr
->
name
))
return
descr
->
flags
;
MESSAGE
(
"%s: unknown filesystem type
%s
, defaulting to 'win95'.
\n
"
,
debugstr_w
(
name
),
debugstr_w
(
value
)
);
return
DRIVE_CASE_PRESERVING
;
}
...
...
@@ -177,32 +183,55 @@ static UINT DRIVE_GetFSFlags( const char *name, const char *value )
int
DRIVE_Init
(
void
)
{
int
i
,
len
,
count
=
0
;
char
name
[]
=
"Drive A"
;
char
drive_env
[]
=
"=A:"
;
char
path
[
MAX_PATHNAME_LEN
];
char
buffer
[
80
];
WCHAR
name
[]
=
{
'D'
,
'r'
,
'i'
,
'v'
,
'e'
,
' '
,
'A'
,
0
}
;
WCHAR
drive_env
[]
=
{
'='
,
'A'
,
':'
,
0
}
;
WCHAR
path
[
MAX_PATHNAME_LEN
];
WCHAR
buffer
[
80
];
struct
stat
drive_stat_buffer
;
char
*
p
;
WCHAR
*
p
;
DOSDRIVE
*
drive
;
static
const
WCHAR
PathW
[]
=
{
'P'
,
'a'
,
't'
,
'h'
,
0
};
static
const
WCHAR
empty_strW
[]
=
{
0
};
static
const
WCHAR
CodepageW
[]
=
{
'C'
,
'o'
,
'd'
,
'e'
,
'p'
,
'a'
,
'g'
,
'e'
,
0
};
static
const
WCHAR
LabelW
[]
=
{
'L'
,
'a'
,
'b'
,
'e'
,
'l'
,
0
};
static
const
WCHAR
SerialW
[]
=
{
'S'
,
'e'
,
'r'
,
'i'
,
'a'
,
'l'
,
0
};
static
const
WCHAR
zeroW
[]
=
{
'0'
,
0
};
static
const
WCHAR
def_serialW
[]
=
{
'1'
,
'2'
,
'3'
,
'4'
,
'5'
,
'6'
,
'7'
,
'8'
,
0
};
static
const
WCHAR
FilesystemW
[]
=
{
'F'
,
'i'
,
'l'
,
'e'
,
's'
,
'y'
,
's'
,
't'
,
'e'
,
'm'
,
0
};
static
const
WCHAR
win95W
[]
=
{
'w'
,
'i'
,
'n'
,
'9'
,
'5'
,
0
};
static
const
WCHAR
DeviceW
[]
=
{
'D'
,
'e'
,
'v'
,
'i'
,
'c'
,
'e'
,
0
};
static
const
WCHAR
ReadVolInfoW
[]
=
{
'R'
,
'e'
,
'a'
,
'd'
,
'V'
,
'o'
,
'l'
,
'I'
,
'n'
,
'f'
,
'o'
,
0
};
static
const
WCHAR
FailReadOnlyW
[]
=
{
'F'
,
'a'
,
'i'
,
'l'
,
'R'
,
'e'
,
'a'
,
'd'
,
'O'
,
'n'
,
'l'
,
'y'
,
0
};
static
const
WCHAR
driveC_labelW
[]
=
{
'D'
,
'r'
,
'i'
,
'v'
,
'e'
,
' '
,
'C'
,
' '
,
' '
,
' '
,
' '
,
0
};
for
(
i
=
0
,
drive
=
DOSDrives
;
i
<
MAX_DOS_DRIVES
;
i
++
,
name
[
6
]
++
,
drive
++
)
{
PROFILE_GetWineIniString
(
name
,
"Path"
,
""
,
path
,
sizeof
(
path
)
-
1
);
PROFILE_GetWineIniString
(
name
,
PathW
,
empty_strW
,
path
,
MAX_PATHNAME_LEN
);
if
(
path
[
0
])
{
p
=
path
+
strlen
(
path
)
-
1
;
/* Get the code page number */
PROFILE_GetWineIniString
(
name
,
CodepageW
,
zeroW
,
/* 0 == CP_ACP */
buffer
,
80
);
drive
->
codepage
=
strtolW
(
buffer
,
NULL
,
10
);
p
=
path
+
strlenW
(
path
)
-
1
;
while
((
p
>
path
)
&&
(
*
p
==
'/'
))
*
p
--
=
'\0'
;
if
(
path
[
0
]
==
'/'
)
{
drive
->
root
=
heap_strdup
(
path
);
len
=
WideCharToMultiByte
(
drive
->
codepage
,
0
,
path
,
-
1
,
NULL
,
0
,
NULL
,
NULL
);
drive
->
root
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
);
WideCharToMultiByte
(
drive
->
codepage
,
0
,
path
,
-
1
,
drive
->
root
,
len
,
NULL
,
NULL
);
}
else
{
/* relative paths are relative to config dir */
const
char
*
config
=
wine_get_config_dir
();
drive
->
root
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlen
(
config
)
+
strlen
(
path
)
+
2
);
sprintf
(
drive
->
root
,
"%s/%s"
,
config
,
path
);
len
=
strlen
(
config
);
len
+=
WideCharToMultiByte
(
drive
->
codepage
,
0
,
path
,
-
1
,
NULL
,
0
,
NULL
,
NULL
)
+
2
;
drive
->
root
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
);
len
-=
sprintf
(
drive
->
root
,
"%s/"
,
config
);
WideCharToMultiByte
(
drive
->
codepage
,
0
,
path
,
-
1
,
drive
->
root
+
strlen
(
drive
->
root
),
len
,
NULL
,
NULL
);
}
if
(
stat
(
drive
->
root
,
&
drive_stat_buffer
))
...
...
@@ -222,7 +251,7 @@ int DRIVE_Init(void)
continue
;
}
drive
->
dos_cwd
=
heap_strdup
(
""
);
drive
->
dos_cwd
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
drive
->
dos_cwd
[
0
])
);
drive
->
unix_cwd
=
heap_strdup
(
""
);
drive
->
type
=
DRIVE_GetDriveType
(
name
);
drive
->
device
=
NULL
;
...
...
@@ -231,36 +260,38 @@ int DRIVE_Init(void)
drive
->
ino
=
drive_stat_buffer
.
st_ino
;
/* Get the drive label */
PROFILE_GetWineIniString
(
name
,
"Label"
,
""
,
drive
->
label_conf
,
12
);
if
((
len
=
strlen
(
drive
->
label_conf
))
<
11
)
PROFILE_GetWineIniString
(
name
,
LabelW
,
empty_strW
,
drive
->
label_conf
,
12
);
if
((
len
=
strlen
W
(
drive
->
label_conf
))
<
11
)
{
/* Pad label with spaces */
memset
(
drive
->
label_conf
+
len
,
' '
,
11
-
len
)
;
while
(
len
<
11
)
drive
->
label_conf
[
len
++
]
=
' '
;
drive
->
label_conf
[
11
]
=
'\0'
;
}
/* Get the serial number */
PROFILE_GetWineIniString
(
name
,
"Serial"
,
"12345678"
,
buffer
,
sizeof
(
buffer
)
);
drive
->
serial_conf
=
strtoul
(
buffer
,
NULL
,
16
);
PROFILE_GetWineIniString
(
name
,
SerialW
,
def_serialW
,
buffer
,
80
);
drive
->
serial_conf
=
strtolW
(
buffer
,
NULL
,
16
);
/* Get the filesystem type */
PROFILE_GetWineIniString
(
name
,
"Filesystem"
,
"win95"
,
buffer
,
sizeof
(
buffer
)
);
PROFILE_GetWineIniString
(
name
,
FilesystemW
,
win95W
,
buffer
,
80
);
drive
->
flags
=
DRIVE_GetFSFlags
(
name
,
buffer
);
/* Get the device */
PROFILE_GetWineIniString
(
name
,
"Device"
,
""
,
buffer
,
sizeof
(
buffer
)
);
PROFILE_GetWineIniString
(
name
,
DeviceW
,
empty_strW
,
buffer
,
80
);
if
(
buffer
[
0
])
{
int
cd_fd
;
drive
->
device
=
heap_strdup
(
buffer
);
if
(
PROFILE_GetWineIniBool
(
name
,
"ReadVolInfo"
,
1
))
len
=
WideCharToMultiByte
(
CP_ACP
,
0
,
buffer
,
-
1
,
NULL
,
0
,
NULL
,
NULL
);
drive
->
device
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
);
WideCharToMultiByte
(
drive
->
codepage
,
0
,
buffer
,
-
1
,
drive
->
device
,
len
,
NULL
,
NULL
);
if
(
PROFILE_GetWineIniBool
(
name
,
ReadVolInfoW
,
1
))
drive
->
flags
|=
DRIVE_READ_VOL_INFO
;
if
(
drive
->
type
==
DRIVE_CDROM
)
{
if
((
cd_fd
=
open
(
buffer
,
O_RDONLY
|
O_NONBLOCK
))
!=
-
1
)
{
if
((
cd_fd
=
open
(
drive
->
device
,
O_RDONLY
|
O_NONBLOCK
))
!=
-
1
)
{
CDROM_InitRegistry
(
cd_fd
);
close
(
cd_fd
);
}
...
...
@@ -268,7 +299,7 @@ int DRIVE_Init(void)
}
/* Get the FailReadOnly flag */
if
(
PROFILE_GetWineIniBool
(
name
,
"FailReadOnly"
,
0
))
if
(
PROFILE_GetWineIniBool
(
name
,
FailReadOnlyW
,
0
))
drive
->
flags
|=
DRIVE_FAIL_READ_ONLY
;
/* Make the first hard disk the current drive */
...
...
@@ -276,13 +307,13 @@ int DRIVE_Init(void)
DRIVE_CurDrive
=
i
;
count
++
;
TRACE
(
"%s: path=%s type=%s label=
'%s'
serial=%08lx "
"flags=%08x dev=%x ino=%x
\n
"
,
name
,
drive
->
root
,
DRIVE_Types
[
drive
->
type
]
,
d
rive
->
label_conf
,
drive
->
serial_conf
,
drive
->
flags
,
(
int
)
drive
->
dev
,
(
int
)
drive
->
ino
);
TRACE
(
"%s: path=%s type=%s label=
%s
serial=%08lx "
"flags=%08x
codepage=%u
dev=%x ino=%x
\n
"
,
debugstr_w
(
name
),
drive
->
root
,
debugstr_w
(
DRIVE_Types
[
drive
->
type
])
,
d
ebugstr_w
(
drive
->
label_conf
)
,
drive
->
serial_conf
,
drive
->
flags
,
drive
->
codepage
,
(
int
)
drive
->
dev
,
(
int
)
drive
->
ino
);
}
else
WARN
(
"%s: not defined
\n
"
,
name
);
else
WARN
(
"%s: not defined
\n
"
,
debugstr_w
(
name
)
);
}
if
(
!
count
)
...
...
@@ -290,9 +321,9 @@ int DRIVE_Init(void)
MESSAGE
(
"Warning: no valid DOS drive found, check your configuration file.
\n
"
);
/* Create a C drive pointing to Unix root dir */
DOSDrives
[
2
].
root
=
heap_strdup
(
"/"
);
DOSDrives
[
2
].
dos_cwd
=
heap_strdup
(
""
);
DOSDrives
[
2
].
dos_cwd
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
DOSDrives
[
2
].
dos_cwd
[
0
])
);
DOSDrives
[
2
].
unix_cwd
=
heap_strdup
(
""
);
strcpy
(
DOSDrives
[
2
].
label_conf
,
"Drive C "
);
strcpy
W
(
DOSDrives
[
2
].
label_conf
,
driveC_labelW
);
DOSDrives
[
2
].
serial_conf
=
12345678
;
DOSDrives
[
2
].
type
=
DRIVE_FIXED
;
DOSDrives
[
2
].
device
=
NULL
;
...
...
@@ -316,9 +347,9 @@ int DRIVE_Init(void)
/* get current working directory info for all drives */
for
(
i
=
0
;
i
<
MAX_DOS_DRIVES
;
i
++
,
drive_env
[
1
]
++
)
{
if
(
!
GetEnvironmentVariable
A
(
drive_env
,
path
,
sizeof
(
path
)
))
continue
;
if
(
!
GetEnvironmentVariable
W
(
drive_env
,
path
,
MAX_PATHNAME_LEN
))
continue
;
/* sanity check */
if
(
toupper
(
path
[
0
])
!=
drive_env
[
1
]
||
path
[
1
]
!=
':'
)
continue
;
if
(
toupper
W
(
path
[
0
])
!=
drive_env
[
1
]
||
path
[
1
]
!=
':'
)
continue
;
DRIVE_Chdir
(
i
,
path
+
2
);
}
return
1
;
...
...
@@ -361,7 +392,6 @@ int DRIVE_SetCurrentDrive( int drive )
TRACE
(
"%c:
\n
"
,
'A'
+
drive
);
DRIVE_CurDrive
=
drive
;
if
(
pTask
)
pTask
->
curdrive
=
drive
|
0x80
;
chdir
(
DRIVE_GetUnixCwd
(
drive
));
return
1
;
}
...
...
@@ -373,6 +403,8 @@ int DRIVE_SetCurrentDrive( int drive )
* This can be used to translate a Unix path into a drive + DOS path.
* Return value is the drive, or -1 on error. On success, path is modified
* to point to the beginning of the DOS path.
*
* Note: path must be in the encoding of the underlying Unix file system.
*/
int
DRIVE_FindDriveRoot
(
const
char
**
path
)
{
...
...
@@ -437,6 +469,45 @@ int DRIVE_FindDriveRoot( const char **path )
/***********************************************************************
* DRIVE_FindDriveRootW
*
* Unicode version of DRIVE_FindDriveRoot.
*/
int
DRIVE_FindDriveRootW
(
LPCWSTR
*
path
)
{
int
drive
,
rootdrive
=
-
1
;
char
buffer
[
MAX_PATHNAME_LEN
];
LPCWSTR
p
=
*
path
;
int
len
,
match_len
=
-
1
;
for
(
drive
=
0
;
drive
<
MAX_DOS_DRIVES
;
drive
++
)
{
if
(
!
DOSDrives
[
drive
].
root
||
(
DOSDrives
[
drive
].
flags
&
DRIVE_DISABLED
))
continue
;
WideCharToMultiByte
(
DOSDrives
[
drive
].
codepage
,
0
,
*
path
,
-
1
,
buffer
,
MAX_PATHNAME_LEN
,
NULL
,
NULL
);
len
=
strlen
(
DOSDrives
[
drive
].
root
);
if
(
strncmp
(
DOSDrives
[
drive
].
root
,
buffer
,
len
))
continue
;
if
(
len
<=
match_len
)
continue
;
match_len
=
len
;
rootdrive
=
drive
;
p
=
*
path
+
len
;
}
if
(
rootdrive
!=
-
1
)
{
*
path
=
p
;
TRACE
(
"%s -> drive %c:, root='%s', name=%s
\n
"
,
buffer
,
'A'
+
rootdrive
,
DOSDrives
[
rootdrive
].
root
,
debugstr_w
(
*
path
)
);
}
return
rootdrive
;
}
/***********************************************************************
* DRIVE_GetRoot
*/
const
char
*
DRIVE_GetRoot
(
int
drive
)
...
...
@@ -449,7 +520,7 @@ const char * DRIVE_GetRoot( int drive )
/***********************************************************************
* DRIVE_GetDosCwd
*/
const
char
*
DRIVE_GetDosCwd
(
int
drive
)
LPCWSTR
DRIVE_GetDosCwd
(
int
drive
)
{
TDB
*
pTask
=
TASK_GetCurrent
();
if
(
!
DRIVE_IsValid
(
drive
))
return
NULL
;
...
...
@@ -459,8 +530,11 @@ const char * DRIVE_GetDosCwd( int drive )
((
pTask
->
curdrive
&
~
0x80
)
==
drive
)
&&
/* and it's the one we want */
(
DRIVE_LastTask
!=
GetCurrentTask
()))
/* and the task changed */
{
static
const
WCHAR
rootW
[]
=
{
'\\'
,
0
};
WCHAR
curdirW
[
MAX_PATH
];
MultiByteToWideChar
(
CP_ACP
,
0
,
pTask
->
curdir
,
-
1
,
curdirW
,
MAX_PATH
);
/* Perform the task-switch */
if
(
!
DRIVE_Chdir
(
drive
,
pTask
->
curdir
))
DRIVE_Chdir
(
drive
,
"
\\
"
);
if
(
!
DRIVE_Chdir
(
drive
,
curdirW
))
DRIVE_Chdir
(
drive
,
rootW
);
DRIVE_LastTask
=
GetCurrentTask
();
}
return
DOSDrives
[
drive
].
dos_cwd
;
...
...
@@ -480,8 +554,11 @@ const char * DRIVE_GetUnixCwd( int drive )
((
pTask
->
curdrive
&
~
0x80
)
==
drive
)
&&
/* and it's the one we want */
(
DRIVE_LastTask
!=
GetCurrentTask
()))
/* and the task changed */
{
static
const
WCHAR
rootW
[]
=
{
'\\'
,
0
};
WCHAR
curdirW
[
MAX_PATH
];
MultiByteToWideChar
(
CP_ACP
,
0
,
pTask
->
curdir
,
-
1
,
curdirW
,
MAX_PATH
);
/* Perform the task-switch */
if
(
!
DRIVE_Chdir
(
drive
,
pTask
->
curdir
))
DRIVE_Chdir
(
drive
,
"
\\
"
);
if
(
!
DRIVE_Chdir
(
drive
,
curdirW
))
DRIVE_Chdir
(
drive
,
rootW
);
DRIVE_LastTask
=
GetCurrentTask
();
}
return
DOSDrives
[
drive
].
unix_cwd
;
...
...
@@ -661,18 +738,15 @@ int DRIVE_WriteSuperblockEntry (int drive, off_t ofs, size_t len, char * buff)
*/
static
HANDLE
CDROM_Open
(
int
drive
)
{
char
root
[
6
];
strcpy
(
root
,
"
\\\\
.
\\
A:"
);
WCHAR
root
[]
=
{
'\\'
,
'\\'
,
'.'
,
'\\'
,
'A'
,
':'
,
0
};
root
[
4
]
+=
drive
;
return
CreateFileA
(
root
,
GENERIC_READ
,
FILE_SHARE_READ
,
NULL
,
OPEN_EXISTING
,
0
,
0
);
return
CreateFileW
(
root
,
GENERIC_READ
,
FILE_SHARE_READ
,
NULL
,
OPEN_EXISTING
,
0
,
0
);
}
/**************************************************************************
* CDROM_Data_GetLabel [internal]
*/
DWORD
CDROM_Data_GetLabel
(
int
drive
,
char
*
label
)
DWORD
CDROM_Data_GetLabel
(
int
drive
,
WCHAR
*
label
)
{
#define LABEL_LEN 32+1
int
dev
=
open
(
DOSDrives
[
drive
].
device
,
O_RDONLY
|
O_NONBLOCK
);
...
...
@@ -702,12 +776,12 @@ DWORD CDROM_Data_GetLabel(int drive, char *label)
ch
=
label_read
[
i
];
label_read
[
i
]
=
(
ch
<<
8
)
|
(
ch
>>
8
);
}
WideCharToMultiByte
(
CP_ACP
,
0
,
label_read
,
-
1
,
label
,
12
,
NULL
,
NULL
);
strncpyW
(
label
,
label_read
,
11
);
label
[
11
]
=
0
;
}
else
{
strncpy
(
label
,
(
LPSTR
)
label_read
,
11
);
MultiByteToWideChar
(
DOSDrives
[
drive
].
codepage
,
0
,
(
LPSTR
)
label_read
,
-
1
,
label
,
11
);
label
[
11
]
=
'\0'
;
}
return
1
;
...
...
@@ -722,7 +796,7 @@ failure:
/**************************************************************************
* CDROM_GetLabel [internal]
*/
static
DWORD
CDROM_GetLabel
(
int
drive
,
char
*
label
)
static
DWORD
CDROM_GetLabel
(
int
drive
,
WCHAR
*
label
)
{
HANDLE
h
=
CDROM_Open
(
drive
);
CDROM_DISK_DATA
cdd
;
...
...
@@ -739,8 +813,11 @@ static DWORD CDROM_GetLabel(int drive, char *label)
ret
=
0
;
break
;
case
CDROM_DISK_AUDIO_TRACK
:
strcpy
(
label
,
"Audio CD "
);
{
static
const
WCHAR
audioCD
[]
=
{
'A'
,
'u'
,
'd'
,
'i'
,
'o'
,
' '
,
'C'
,
'D'
,
' '
,
' '
,
' '
,
0
};
strcpyW
(
label
,
audioCD
);
break
;
}
case
CDROM_DISK_DATA_TRACK
|
CDROM_DISK_AUDIO_TRACK
:
FIXME
(
"Need to get the label of a mixed mode CD: not implemented yet !
\n
"
);
/* fall through */
...
...
@@ -748,14 +825,14 @@ static DWORD CDROM_GetLabel(int drive, char *label)
ret
=
0
;
break
;
}
TRACE
(
"CD: label is
'%s'.
\n
"
,
label
);
TRACE
(
"CD: label is
%s
\n
"
,
debugstr_w
(
label
)
);
return
ret
;
}
/***********************************************************************
* DRIVE_GetLabel
*/
const
char
*
DRIVE_GetLabel
(
int
drive
)
LPCWSTR
DRIVE_GetLabel
(
int
drive
)
{
int
read
=
0
;
char
buff
[
DRIVE_SUPER
];
...
...
@@ -778,7 +855,9 @@ const char * DRIVE_GetLabel( int drive )
offs
=
0x2b
;
/* FIXME: ISO9660 uses a 32 bytes long label. Should we do also? */
if
(
offs
!=
-
1
)
memcpy
(
DOSDrives
[
drive
].
label_read
,
buff
+
offs
,
11
);
if
(
offs
!=
-
1
)
MultiByteToWideChar
(
DOSDrives
[
drive
].
codepage
,
0
,
buff
+
offs
,
11
,
DOSDrives
[
drive
].
label_read
,
11
);
DOSDrives
[
drive
].
label_read
[
11
]
=
'\0'
;
read
=
1
;
}
...
...
@@ -923,6 +1002,8 @@ DWORD DRIVE_GetSerialNumber( int drive )
DWORD
serial
=
0
;
char
buff
[
DRIVE_SUPER
];
TRACE
(
"drive %d, type = %d
\n
"
,
drive
,
DOSDrives
[
drive
].
type
);
if
(
!
DRIVE_IsValid
(
drive
))
return
0
;
if
(
DOSDrives
[
drive
].
flags
&
DRIVE_READ_VOL_INFO
)
...
...
@@ -980,7 +1061,7 @@ int DRIVE_SetSerialNumber( int drive, DWORD serial )
*/
static
UINT
DRIVE_GetType
(
int
drive
)
{
if
(
!
DRIVE_IsValid
(
drive
))
return
DRIVE_
UNKNOWN
;
if
(
!
DRIVE_IsValid
(
drive
))
return
DRIVE_
NO_ROOT_DIR
;
return
DOSDrives
[
drive
].
type
;
}
...
...
@@ -994,22 +1075,33 @@ UINT DRIVE_GetFlags( int drive )
return
DOSDrives
[
drive
].
flags
;
}
/***********************************************************************
* DRIVE_GetCodepage
*/
UINT
DRIVE_GetCodepage
(
int
drive
)
{
if
((
drive
<
0
)
||
(
drive
>=
MAX_DOS_DRIVES
))
return
0
;
return
DOSDrives
[
drive
].
codepage
;
}
/***********************************************************************
* DRIVE_Chdir
*/
int
DRIVE_Chdir
(
int
drive
,
const
char
*
path
)
int
DRIVE_Chdir
(
int
drive
,
LPCWSTR
path
)
{
DOS_FULL_NAME
full_name
;
char
buffer
[
MAX_PATHNAME_LEN
];
WCHAR
buffer
[
MAX_PATHNAME_LEN
];
LPSTR
unix_cwd
;
BY_HANDLE_FILE_INFORMATION
info
;
TDB
*
pTask
=
TASK_GetCurrent
();
strcpy
(
buffer
,
"A:"
);
buffer
[
0
]
+=
drive
;
TRACE
(
"(%s,%s)
\n
"
,
buffer
,
path
);
lstrcpynA
(
buffer
+
2
,
path
,
sizeof
(
buffer
)
-
2
);
buffer
[
0
]
=
'A'
+
drive
;
buffer
[
1
]
=
':'
;
buffer
[
2
]
=
0
;
TRACE
(
"(%s,%s)
\n
"
,
debugstr_w
(
buffer
),
debugstr_w
(
path
)
);
strncpyW
(
buffer
+
2
,
path
,
MAX_PATHNAME_LEN
-
2
);
buffer
[
MAX_PATHNAME_LEN
-
1
]
=
0
;
/* ensure 0 termination */
if
(
!
DOSFS_GetFullName
(
buffer
,
TRUE
,
&
full_name
))
return
0
;
if
(
!
FILE_Stat
(
full_name
.
long_name
,
&
info
))
return
0
;
...
...
@@ -1022,20 +1114,20 @@ int DRIVE_Chdir( int drive, const char *path )
while
(
*
unix_cwd
==
'/'
)
unix_cwd
++
;
TRACE
(
"(%c:): unix_cwd=%s dos_cwd=%s
\n
"
,
'A'
+
drive
,
unix_cwd
,
full_name
.
short_name
+
3
);
'A'
+
drive
,
unix_cwd
,
debugstr_w
(
full_name
.
short_name
+
3
)
);
HeapFree
(
GetProcessHeap
(),
0
,
DOSDrives
[
drive
].
dos_cwd
);
HeapFree
(
GetProcessHeap
(),
0
,
DOSDrives
[
drive
].
unix_cwd
);
DOSDrives
[
drive
].
dos_cwd
=
heap_strdup
(
full_name
.
short_name
+
3
);
DOSDrives
[
drive
].
dos_cwd
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
strlenW
(
full_name
.
short_name
)
-
2
)
*
sizeof
(
WCHAR
));
strcpyW
(
DOSDrives
[
drive
].
dos_cwd
,
full_name
.
short_name
+
3
);
DOSDrives
[
drive
].
unix_cwd
=
heap_strdup
(
unix_cwd
);
if
(
pTask
&&
(
pTask
->
curdrive
&
0x80
)
&&
((
pTask
->
curdrive
&
~
0x80
)
==
drive
))
{
lstrcpynA
(
pTask
->
curdir
,
full_name
.
short_name
+
2
,
sizeof
(
pTask
->
curdir
)
);
WideCharToMultiByte
(
CP_ACP
,
0
,
full_name
.
short_name
+
2
,
-
1
,
pTask
->
curdir
,
sizeof
(
pTask
->
curdir
),
NULL
,
NULL
);
DRIVE_LastTask
=
GetCurrentTask
();
chdir
(
unix_cwd
);
/* Only change if on current drive */
}
return
1
;
}
...
...
@@ -1103,7 +1195,8 @@ int DRIVE_SetLogicalMapping ( int existing_drive, int new_drive )
}
new
->
root
=
heap_strdup
(
old
->
root
);
new
->
dos_cwd
=
heap_strdup
(
old
->
dos_cwd
);
new
->
dos_cwd
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
strlenW
(
old
->
dos_cwd
)
+
1
)
*
sizeof
(
WCHAR
));
strcpyW
(
new
->
dos_cwd
,
old
->
dos_cwd
);
new
->
unix_cwd
=
heap_strdup
(
old
->
unix_cwd
);
new
->
device
=
heap_strdup
(
old
->
device
);
memcpy
(
new
->
label_conf
,
old
->
label_conf
,
12
);
...
...
@@ -1198,7 +1291,7 @@ static int DRIVE_GetFreeSpace( int drive, PULARGE_INTEGER size,
if
(
!
DRIVE_IsValid
(
drive
))
{
SetLastError
(
ERROR_
INVALID_DRIVE
);
SetLastError
(
ERROR_
PATH_NOT_FOUND
);
return
0
;
}
...
...
@@ -1238,18 +1331,18 @@ static int DRIVE_GetFreeSpace( int drive, PULARGE_INTEGER size,
* Despite the API description, return required length including the
* terminating null when buffer too small. This is the real behaviour.
*/
static
UINT
DRIVE_GetCurrentDirectory
(
UINT
buflen
,
LPSTR
buf
)
static
UINT
DRIVE_GetCurrentDirectory
(
UINT
buflen
,
LPWSTR
buf
)
{
UINT
ret
;
const
char
*
s
=
DRIVE_GetDosCwd
(
DRIVE_GetCurrentDrive
()
);
LPCWSTR
dos_cwd
=
DRIVE_GetDosCwd
(
DRIVE_GetCurrentDrive
()
);
static
const
WCHAR
driveA_rootW
[]
=
{
'A'
,
':'
,
'\\'
,
0
};
assert
(
s
);
ret
=
strlen
(
s
)
+
3
;
/* length of WHOLE current directory */
ret
=
strlenW
(
dos_cwd
)
+
3
;
/* length of WHOLE current directory */
if
(
ret
>=
buflen
)
return
ret
+
1
;
lstrcpynA
(
buf
,
"A:
\\
"
,
min
(
4u
,
buflen
)
);
if
(
buflen
)
buf
[
0
]
+=
DRIVE_GetCurrentDrive
();
if
(
buflen
>
3
)
lstrcpynA
(
buf
+
3
,
s
,
buflen
-
3
);
strcpyW
(
buf
,
driveA_rootW
);
buf
[
0
]
+=
DRIVE_GetCurrentDrive
();
strcatW
(
buf
,
dos_cwd
);
return
ret
;
}
...
...
@@ -1263,18 +1356,25 @@ static UINT DRIVE_GetCurrentDirectory( UINT buflen, LPSTR buf )
char
*
DRIVE_BuildEnv
(
void
)
{
int
i
,
length
=
0
;
const
char
*
cwd
[
MAX_DOS_DRIVES
];
LPCWSTR
cwd
[
MAX_DOS_DRIVES
];
char
*
env
,
*
p
;
for
(
i
=
0
;
i
<
MAX_DOS_DRIVES
;
i
++
)
{
if
((
cwd
[
i
]
=
DRIVE_GetDosCwd
(
i
))
&&
cwd
[
i
][
0
])
length
+=
strlen
(
cwd
[
i
])
+
8
;
if
((
cwd
[
i
]
=
DRIVE_GetDosCwd
(
i
))
&&
cwd
[
i
][
0
])
length
+=
WideCharToMultiByte
(
DRIVE_GetCodepage
(
i
),
0
,
cwd
[
i
],
-
1
,
NULL
,
0
,
NULL
,
NULL
)
+
7
;
}
if
(
!
(
env
=
HeapAlloc
(
GetProcessHeap
(),
0
,
length
+
1
)))
return
NULL
;
for
(
i
=
0
,
p
=
env
;
i
<
MAX_DOS_DRIVES
;
i
++
)
{
if
(
cwd
[
i
]
&&
cwd
[
i
][
0
])
p
+=
sprintf
(
p
,
"=%c:=%c:
\\
%s"
,
'A'
+
i
,
'A'
+
i
,
cwd
[
i
]
)
+
1
;
{
*
p
++
=
'='
;
*
p
++
=
'A'
+
i
;
*
p
++
=
':'
;
*
p
++
=
'='
;
*
p
++
=
'A'
+
i
;
*
p
++
=
':'
;
*
p
++
=
'\\'
;
WideCharToMultiByte
(
DRIVE_GetCodepage
(
i
),
0
,
cwd
[
i
],
-
1
,
p
,
0x7fffffff
,
NULL
,
NULL
);
p
+=
strlen
(
p
)
+
1
;
}
}
*
p
=
0
;
return
env
;
...
...
@@ -1294,7 +1394,7 @@ BOOL16 WINAPI GetDiskFreeSpace16( LPCSTR root, LPDWORD cluster_sectors,
/***********************************************************************
* GetDiskFreeSpace
A
(KERNEL32.@)
* GetDiskFreeSpace
W
(KERNEL32.@)
*
* Fails if expression resulting from current drive's dir and "root"
* is not a root dir of the target drive.
...
...
@@ -1320,27 +1420,38 @@ BOOL16 WINAPI GetDiskFreeSpace16( LPCSTR root, LPDWORD cluster_sectors,
* "E:\\TEST" "C:" TRUE (when CurrDir of "C:" set to "\\")
* "E:\\TEST" "C:" FALSE (when CurrDir of "C:" set to "\\TEST")
*/
BOOL
WINAPI
GetDiskFreeSpace
A
(
LPC
STR
root
,
LPDWORD
cluster_sectors
,
BOOL
WINAPI
GetDiskFreeSpace
W
(
LPCW
STR
root
,
LPDWORD
cluster_sectors
,
LPDWORD
sector_bytes
,
LPDWORD
free_clusters
,
LPDWORD
total_clusters
)
{
int
drive
,
sec_size
;
ULARGE_INTEGER
size
,
available
;
LPCSTR
path
;
LPC
W
STR
path
;
DWORD
cluster_sec
;
if
((
!
root
)
||
(
strcmp
(
root
,
"
\\
"
)
==
0
))
TRACE
(
"%s,%p,%p,%p,%p
\n
"
,
debugstr_w
(
root
),
cluster_sectors
,
sector_bytes
,
free_clusters
,
total_clusters
);
if
(
!
root
||
root
[
0
]
==
'\\'
||
root
[
0
]
==
'/'
)
drive
=
DRIVE_GetCurrentDrive
();
else
if
(
(
strlen
(
root
)
>=
2
)
&&
(
root
[
1
]
==
':'
)
)
/* root contains drive tag */
if
(
root
[
0
]
&&
root
[
1
]
==
':'
)
/* root contains drive tag */
{
drive
=
toupper
(
root
[
0
])
-
'A'
;
drive
=
toupper
W
(
root
[
0
])
-
'A'
;
path
=
&
root
[
2
];
if
(
path
[
0
]
==
'\0'
)
{
path
=
DRIVE_GetDosCwd
(
drive
);
if
(
!
path
)
{
SetLastError
(
ERROR_PATH_NOT_FOUND
);
return
FALSE
;
}
}
else
if
(
path
[
0
]
==
'\\'
)
path
++
;
if
(
path
[
0
])
/* oops, we are in a subdir */
{
SetLastError
(
ERROR_INVALID_NAME
);
...
...
@@ -1349,7 +1460,10 @@ BOOL WINAPI GetDiskFreeSpaceA( LPCSTR root, LPDWORD cluster_sectors,
}
else
{
SetLastError
(
ERROR_INVALID_NAME
);
if
(
!
root
[
0
])
SetLastError
(
ERROR_PATH_NOT_FOUND
);
else
SetLastError
(
ERROR_INVALID_NAME
);
return
FALSE
;
}
...
...
@@ -1386,19 +1500,30 @@ BOOL WINAPI GetDiskFreeSpaceA( LPCSTR root, LPDWORD cluster_sectors,
/***********************************************************************
* GetDiskFreeSpace
W
(KERNEL32.@)
* GetDiskFreeSpace
A
(KERNEL32.@)
*/
BOOL
WINAPI
GetDiskFreeSpace
W
(
LPCW
STR
root
,
LPDWORD
cluster_sectors
,
BOOL
WINAPI
GetDiskFreeSpace
A
(
LPC
STR
root
,
LPDWORD
cluster_sectors
,
LPDWORD
sector_bytes
,
LPDWORD
free_clusters
,
LPDWORD
total_clusters
)
{
LPSTR
xroot
;
BOOL
ret
;
UNICODE_STRING
rootW
;
BOOL
ret
=
FALSE
;
if
(
root
)
{
if
(
!
RtlCreateUnicodeStringFromAsciiz
(
&
rootW
,
root
))
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
FALSE
;
}
}
else
rootW
.
Buffer
=
NULL
;
ret
=
GetDiskFreeSpaceW
(
rootW
.
Buffer
,
cluster_sectors
,
sector_bytes
,
free_clusters
,
total_clusters
);
RtlFreeUnicodeString
(
&
rootW
);
xroot
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
root
);
ret
=
GetDiskFreeSpaceA
(
xroot
,
cluster_sectors
,
sector_bytes
,
free_clusters
,
total_clusters
);
HeapFree
(
GetProcessHeap
(),
0
,
xroot
);
return
ret
;
}
...
...
@@ -1516,7 +1641,7 @@ UINT16 WINAPI GetDriveType16( UINT16 drive ) /* [in] number (NOT letter) of driv
/***********************************************************************
* GetDriveType
A
(KERNEL32.@)
* GetDriveType
W
(KERNEL32.@)
*
* Returns the type of the disk drive specified. If root is NULL the
* root of the current directory is used.
...
...
@@ -1533,34 +1658,49 @@ UINT16 WINAPI GetDriveType16( UINT16 drive ) /* [in] number (NOT letter) of driv
* DRIVE_CDROM CDROM drive
* DRIVE_RAMDISK virtual disk in RAM
*/
UINT
WINAPI
GetDriveType
A
(
LPC
STR
root
)
/* [in] String describing drive */
UINT
WINAPI
GetDriveType
W
(
LPCW
STR
root
)
/* [in] String describing drive */
{
int
drive
;
TRACE
(
"(%s)
\n
"
,
debugstr_
a
(
root
));
TRACE
(
"(%s)
\n
"
,
debugstr_
w
(
root
));
if
(
NULL
==
root
)
drive
=
DRIVE_GetCurrentDrive
();
else
{
if
((
root
[
1
])
&&
(
root
[
1
]
!=
':'
))
{
WARN
(
"invalid root %s
\n
"
,
debugstr_
a
(
root
));
WARN
(
"invalid root %s
\n
"
,
debugstr_
w
(
root
));
return
DRIVE_NO_ROOT_DIR
;
}
drive
=
toupper
(
root
[
0
])
-
'A'
;
drive
=
toupper
W
(
root
[
0
])
-
'A'
;
}
return
DRIVE_GetType
(
drive
);
}
/***********************************************************************
* GetDriveType
W
(KERNEL32.@)
* GetDriveType
A
(KERNEL32.@)
*/
UINT
WINAPI
GetDriveType
W
(
LPCW
STR
root
)
UINT
WINAPI
GetDriveType
A
(
LPC
STR
root
)
{
LPSTR
xpath
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
root
);
UINT
ret
=
GetDriveTypeA
(
xpath
);
HeapFree
(
GetProcessHeap
(),
0
,
xpath
);
UNICODE_STRING
rootW
;
UINT
ret
=
0
;
if
(
root
)
{
if
(
!
RtlCreateUnicodeStringFromAsciiz
(
&
rootW
,
root
))
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
0
;
}
}
else
rootW
.
Buffer
=
NULL
;
ret
=
GetDriveTypeW
(
rootW
.
Buffer
);
RtlFreeUnicodeString
(
&
rootW
);
return
ret
;
}
...
...
@@ -1569,39 +1709,60 @@ UINT WINAPI GetDriveTypeW( LPCWSTR root )
*/
UINT16
WINAPI
GetCurrentDirectory16
(
UINT16
buflen
,
LPSTR
buf
)
{
return
(
UINT16
)
DRIVE_GetCurrentDirectory
(
buflen
,
buf
);
WCHAR
cur_dirW
[
MAX_PATH
];
DRIVE_GetCurrentDirectory
(
MAX_PATH
,
cur_dirW
);
return
(
UINT16
)
WideCharToMultiByte
(
CP_ACP
,
0
,
cur_dirW
,
-
1
,
buf
,
buflen
,
NULL
,
NULL
);
}
/***********************************************************************
* GetCurrentDirectory
A
(KERNEL32.@)
* GetCurrentDirectory
W
(KERNEL32.@)
*/
UINT
WINAPI
GetCurrentDirectory
A
(
UINT
buflen
,
LP
STR
buf
)
UINT
WINAPI
GetCurrentDirectory
W
(
UINT
buflen
,
LPW
STR
buf
)
{
UINT
ret
;
char
longname
[
MAX_PATHNAME_LEN
];
char
shortname
[
MAX_PATHNAME_LEN
];
WCHAR
longname
[
MAX_PATHNAME_LEN
];
WCHAR
shortname
[
MAX_PATHNAME_LEN
];
ret
=
DRIVE_GetCurrentDirectory
(
MAX_PATHNAME_LEN
,
shortname
);
if
(
ret
>
MAX_PATHNAME_LEN
)
{
ERR_
(
file
)(
"pathnamelength (%d) > MAX_PATHNAME_LEN!
\n
"
,
ret
);
return
ret
;
}
GetLongPathName
A
(
shortname
,
longname
,
MAX_PATHNAME_LEN
);
ret
=
strlen
(
longname
)
+
1
;
GetLongPathName
W
(
shortname
,
longname
,
MAX_PATHNAME_LEN
);
ret
=
strlen
W
(
longname
)
+
1
;
if
(
ret
>
buflen
)
return
ret
;
strcpy
(
buf
,
longname
);
strcpy
W
(
buf
,
longname
);
return
ret
-
1
;
}
/***********************************************************************
* GetCurrentDirectory
W
(KERNEL32.@)
* GetCurrentDirectory
A
(KERNEL32.@)
*/
UINT
WINAPI
GetCurrentDirectory
W
(
UINT
buflen
,
LPW
STR
buf
)
UINT
WINAPI
GetCurrentDirectory
A
(
UINT
buflen
,
LP
STR
buf
)
{
LPSTR
xpath
=
HeapAlloc
(
GetProcessHeap
(),
0
,
buflen
+
1
);
UINT
ret
=
GetCurrentDirectoryA
(
buflen
,
xpath
);
if
(
ret
<
buflen
)
ret
=
MultiByteToWideChar
(
CP_ACP
,
0
,
xpath
,
-
1
,
buf
,
buflen
)
-
1
;
HeapFree
(
GetProcessHeap
(),
0
,
xpath
);
WCHAR
bufferW
[
MAX_PATH
];
DWORD
ret
,
retW
;
retW
=
GetCurrentDirectoryW
(
MAX_PATH
,
bufferW
);
if
(
!
retW
)
ret
=
0
;
else
if
(
retW
>
MAX_PATH
)
{
SetLastError
(
ERROR_FILENAME_EXCED_RANGE
);
ret
=
0
;
}
else
{
ret
=
WideCharToMultiByte
(
CP_ACP
,
0
,
bufferW
,
-
1
,
NULL
,
0
,
NULL
,
NULL
);
if
(
buflen
>=
ret
)
{
WideCharToMultiByte
(
CP_ACP
,
0
,
bufferW
,
-
1
,
buf
,
buflen
,
NULL
,
NULL
);
ret
--
;
/* length without 0 */
}
}
return
ret
;
}
...
...
@@ -1616,19 +1777,20 @@ BOOL16 WINAPI SetCurrentDirectory16( LPCSTR dir )
/***********************************************************************
* SetCurrentDirectory
A
(KERNEL32.@)
* SetCurrentDirectory
W
(KERNEL32.@)
*/
BOOL
WINAPI
SetCurrentDirectory
A
(
LPC
STR
dir
)
BOOL
WINAPI
SetCurrentDirectory
W
(
LPCW
STR
dir
)
{
int
drive
,
olddrive
=
DRIVE_GetCurrentDrive
();
if
(
!
dir
)
{
ERR_
(
file
)(
"(NULL)!
\n
"
);
if
(
!
dir
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
if
(
dir
[
0
]
&&
(
dir
[
1
]
==
':'
))
{
drive
=
toupper
(
*
dir
)
-
'A'
;
drive
=
toupper
W
(
*
dir
)
-
'A'
;
dir
+=
2
;
}
else
...
...
@@ -1638,6 +1800,7 @@ BOOL WINAPI SetCurrentDirectoryA( LPCSTR dir )
sets pTask->curdir only if pTask->curdrive is drive */
if
(
!
(
DRIVE_SetCurrentDrive
(
drive
)))
return
FALSE
;
/* FIXME: what about empty strings? Add a \\ ? */
if
(
!
DRIVE_Chdir
(
drive
,
dir
))
{
DRIVE_SetCurrentDrive
(
olddrive
);
...
...
@@ -1648,14 +1811,27 @@ BOOL WINAPI SetCurrentDirectoryA( LPCSTR dir )
/***********************************************************************
* SetCurrentDirectory
W
(KERNEL32.@)
* SetCurrentDirectory
A
(KERNEL32.@)
*/
BOOL
WINAPI
SetCurrentDirectory
W
(
LPCWSTR
dirW
)
BOOL
WINAPI
SetCurrentDirectory
A
(
LPCSTR
dir
)
{
LPSTR
dir
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
dirW
);
BOOL
res
=
SetCurrentDirectoryA
(
dir
);
HeapFree
(
GetProcessHeap
(),
0
,
dir
);
return
res
;
UNICODE_STRING
dirW
;
BOOL
ret
=
FALSE
;
if
(
!
dir
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
if
(
RtlCreateUnicodeStringFromAsciiz
(
&
dirW
,
dir
))
{
ret
=
SetCurrentDirectoryW
(
dirW
.
Buffer
);
RtlFreeUnicodeString
(
&
dirW
);
}
else
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
ret
;
}
...
...
@@ -1733,33 +1909,34 @@ DWORD WINAPI GetLogicalDrives(void)
/***********************************************************************
* GetVolumeInformation
A
(KERNEL32.@)
* GetVolumeInformation
W
(KERNEL32.@)
*/
BOOL
WINAPI
GetVolumeInformation
A
(
LPCSTR
root
,
LP
STR
label
,
BOOL
WINAPI
GetVolumeInformation
W
(
LPCWSTR
root
,
LPW
STR
label
,
DWORD
label_len
,
DWORD
*
serial
,
DWORD
*
filename_len
,
DWORD
*
flags
,
LPSTR
fsname
,
DWORD
fsname_len
)
LP
W
STR
fsname
,
DWORD
fsname_len
)
{
int
drive
;
char
*
cp
;
LPWSTR
cp
;
/* FIXME, SetLastError()s missing */
if
(
!
root
)
drive
=
DRIVE_GetCurrentDrive
();
else
{
if
(
(
root
[
1
])
&&
(
root
[
1
]
!=
':'
)
)
if
(
root
[
0
]
&&
root
[
1
]
!=
':'
)
{
WARN
(
"invalid root
'%s'
\n
"
,
root
);
WARN
(
"invalid root
%s
\n
"
,
debugstr_w
(
root
)
);
return
FALSE
;
}
drive
=
toupper
(
root
[
0
])
-
'A'
;
drive
=
toupper
W
(
root
[
0
])
-
'A'
;
}
if
(
!
DRIVE_IsValid
(
drive
))
return
FALSE
;
if
(
label
)
if
(
label
&&
label_len
)
{
lstrcpynA
(
label
,
DRIVE_GetLabel
(
drive
),
label_len
);
cp
=
label
+
strlen
(
label
);
strncpyW
(
label
,
DRIVE_GetLabel
(
drive
),
label_len
);
label
[
label_len
-
1
]
=
0
;
/* ensure 0 termination */
cp
=
label
+
strlenW
(
label
);
while
(
cp
!=
label
&&
*
(
cp
-
1
)
==
' '
)
cp
--
;
*
cp
=
'\0'
;
}
...
...
@@ -1782,46 +1959,59 @@ BOOL WINAPI GetVolumeInformationA( LPCSTR root, LPSTR label,
if
(
DOSDrives
[
drive
].
flags
&
DRIVE_CASE_PRESERVING
)
*
flags
|=
FS_CASE_IS_PRESERVED
;
}
if
(
fsname
)
{
if
(
fsname
&&
fsname_len
)
{
/* Diablo checks that return code ... */
if
(
DOSDrives
[
drive
].
type
==
DRIVE_CDROM
)
lstrcpynA
(
fsname
,
"CDFS"
,
fsname_len
);
{
static
const
WCHAR
cdfsW
[]
=
{
'C'
,
'D'
,
'F'
,
'S'
,
0
};
strncpyW
(
fsname
,
cdfsW
,
fsname_len
);
}
else
lstrcpynA
(
fsname
,
"FAT"
,
fsname_len
);
{
static
const
WCHAR
fatW
[]
=
{
'F'
,
'A'
,
'T'
,
0
};
strncpyW
(
fsname
,
fatW
,
fsname_len
);
}
fsname
[
fsname_len
-
1
]
=
0
;
/* ensure 0 termination */
}
return
TRUE
;
}
/***********************************************************************
* GetVolumeInformation
W
(KERNEL32.@)
* GetVolumeInformation
A
(KERNEL32.@)
*/
BOOL
WINAPI
GetVolumeInformation
W
(
LPCWSTR
root
,
LPW
STR
label
,
BOOL
WINAPI
GetVolumeInformation
A
(
LPCSTR
root
,
LP
STR
label
,
DWORD
label_len
,
DWORD
*
serial
,
DWORD
*
filename_len
,
DWORD
*
flags
,
LP
W
STR
fsname
,
DWORD
fsname_len
)
LPSTR
fsname
,
DWORD
fsname_len
)
{
LPSTR
xroot
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
root
);
LPSTR
xvolname
=
label
?
HeapAlloc
(
GetProcessHeap
(),
0
,
label_len
)
:
NULL
;
LPSTR
xfsname
=
fsname
?
HeapAlloc
(
GetProcessHeap
(),
0
,
fsname_len
)
:
NULL
;
BOOL
ret
=
GetVolumeInformationA
(
xroot
,
xvolname
,
label_len
,
serial
,
filename_len
,
flags
,
xfsname
,
fsname_len
);
if
(
ret
)
UNICODE_STRING
rootW
;
LPWSTR
labelW
,
fsnameW
;
BOOL
ret
;
if
(
root
)
RtlCreateUnicodeStringFromAsciiz
(
&
rootW
,
root
);
else
rootW
.
Buffer
=
NULL
;
labelW
=
label
?
HeapAlloc
(
GetProcessHeap
(),
0
,
label_len
*
sizeof
(
WCHAR
))
:
NULL
;
fsnameW
=
fsname
?
HeapAlloc
(
GetProcessHeap
(),
0
,
fsname_len
*
sizeof
(
WCHAR
))
:
NULL
;
if
((
ret
=
GetVolumeInformationW
(
rootW
.
Buffer
,
labelW
,
label_len
,
serial
,
filename_len
,
flags
,
fsnameW
,
fsname_len
)))
{
if
(
label
)
MultiByteToWideChar
(
CP_ACP
,
0
,
xvolname
,
-
1
,
label
,
label_len
);
if
(
fsname
)
MultiByteToWideChar
(
CP_ACP
,
0
,
xfsname
,
-
1
,
fsname
,
fsname_len
);
if
(
label
)
WideCharToMultiByte
(
CP_ACP
,
0
,
labelW
,
-
1
,
label
,
label_len
,
NULL
,
NULL
);
if
(
fsname
)
WideCharToMultiByte
(
CP_ACP
,
0
,
fsnameW
,
-
1
,
fsname
,
fsname_len
,
NULL
,
NULL
);
}
HeapFree
(
GetProcessHeap
(),
0
,
xroot
);
HeapFree
(
GetProcessHeap
(),
0
,
xvolname
);
HeapFree
(
GetProcessHeap
(),
0
,
xfsname
);
RtlFreeUnicodeString
(
&
rootW
);
if
(
labelW
)
HeapFree
(
GetProcessHeap
(),
0
,
labelW
);
if
(
fsnameW
)
HeapFree
(
GetProcessHeap
(),
0
,
fsnameW
);
return
ret
;
}
/***********************************************************************
* SetVolumeLabel
A
(KERNEL32.@)
* SetVolumeLabel
W
(KERNEL32.@)
*/
BOOL
WINAPI
SetVolumeLabel
A
(
LPCSTR
root
,
LPC
STR
volname
)
BOOL
WINAPI
SetVolumeLabel
W
(
LPCWSTR
root
,
LPCW
STR
volname
)
{
int
drive
;
...
...
@@ -1832,32 +2022,37 @@ BOOL WINAPI SetVolumeLabelA( LPCSTR root, LPCSTR volname )
{
if
((
root
[
1
])
&&
(
root
[
1
]
!=
':'
))
{
WARN
(
"invalid root
'%s'
\n
"
,
root
);
WARN
(
"invalid root
%s
\n
"
,
debugstr_w
(
root
)
);
return
FALSE
;
}
drive
=
toupper
(
root
[
0
])
-
'A'
;
drive
=
toupper
W
(
root
[
0
])
-
'A'
;
}
if
(
!
DRIVE_IsValid
(
drive
))
return
FALSE
;
/* some copy protection stuff check this */
if
(
DOSDrives
[
drive
].
type
==
DRIVE_CDROM
)
return
FALSE
;
FIXME
(
"(%s,%s),stub!
\n
"
,
root
,
volname
);
strncpyW
(
DOSDrives
[
drive
].
label_conf
,
volname
,
12
);
DOSDrives
[
drive
].
label_conf
[
12
-
1
]
=
0
;
/* ensure 0 termination */
return
TRUE
;
}
/***********************************************************************
* SetVolumeLabel
W
(KERNEL32.@)
* SetVolumeLabel
A
(KERNEL32.@)
*/
BOOL
WINAPI
SetVolumeLabel
W
(
LPCWSTR
rootpath
,
LPCW
STR
volname
)
BOOL
WINAPI
SetVolumeLabel
A
(
LPCSTR
root
,
LPC
STR
volname
)
{
LPSTR
xroot
,
xvol
;
UNICODE_STRING
rootW
,
volnameW
;
BOOL
ret
;
xroot
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
rootpath
);
xvol
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
volname
);
ret
=
SetVolumeLabelA
(
xroot
,
xvol
);
HeapFree
(
GetProcessHeap
(),
0
,
xroot
);
HeapFree
(
GetProcessHeap
(),
0
,
xvol
);
if
(
root
)
RtlCreateUnicodeStringFromAsciiz
(
&
rootW
,
root
);
else
rootW
.
Buffer
=
NULL
;
if
(
volname
)
RtlCreateUnicodeStringFromAsciiz
(
&
volnameW
,
volname
);
else
volnameW
.
Buffer
=
NULL
;
ret
=
SetVolumeLabelW
(
rootW
.
Buffer
,
volnameW
.
Buffer
);
RtlFreeUnicodeString
(
&
rootW
);
RtlFreeUnicodeString
(
&
volnameW
);
return
ret
;
}
files/file.c
View file @
d75aed2c
...
...
@@ -58,6 +58,8 @@
#include "winerror.h"
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "ntddk.h"
#include "wine/winbase16.h"
#include "wine/server.h"
...
...
@@ -69,6 +71,7 @@
#include "wincon.h"
#include "smb.h"
#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
file
);
...
...
@@ -193,13 +196,10 @@ static void FILE_ConvertOFMode( INT mode, DWORD *access, DWORD *sharing )
*/
int
FILE_strcasecmp
(
const
char
*
str1
,
const
char
*
str2
)
{
for
(;;)
{
int
ret
=
FILE_toupper
(
*
str1
)
-
FILE_toupper
(
*
str2
);
if
(
ret
||
!*
str1
)
return
ret
;
str1
++
;
str2
++
;
}
int
ret
=
0
;
for
(
;
;
str1
++
,
str2
++
)
if
((
ret
=
FILE_toupper
(
*
str1
)
-
FILE_toupper
(
*
str2
))
||
!*
str1
)
break
;
return
ret
;
}
...
...
@@ -453,7 +453,18 @@ HANDLE FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing,
}
}
if
(
err
)
SetLastError
(
RtlNtStatusToDosError
(
err
)
);
if
(
err
)
{
/* In the case file creation was rejected due to CREATE_NEW flag
* was specified and file with that name already exists, correct
* last error is ERROR_FILE_EXISTS and not ERROR_ALREADY_EXISTS.
* Note: RtlNtStatusToDosError is not the subject to blame here.
*/
if
(
err
==
STATUS_OBJECT_NAME_COLLISION
)
SetLastError
(
ERROR_FILE_EXISTS
);
else
SetLastError
(
RtlNtStatusToDosError
(
err
)
);
}
if
(
!
ret
)
WARN
(
"Unable to create file '%s' (GLE %ld)
\n
"
,
filename
,
GetLastError
());
return
ret
;
...
...
@@ -483,13 +494,12 @@ HANDLE FILE_CreateDevice( int client_id, DWORD access, LPSECURITY_ATTRIBUTES sa
return
ret
;
}
static
HANDLE
FILE_OpenPipe
(
LPCSTR
name
,
DWORD
access
)
static
HANDLE
FILE_OpenPipe
(
LPC
W
STR
name
,
DWORD
access
)
{
WCHAR
buffer
[
MAX_PATH
];
HANDLE
ret
;
DWORD
len
=
0
;
if
(
name
&&
!
(
len
=
MultiByteToWideChar
(
CP_ACP
,
0
,
name
,
strlen
(
name
),
buffer
,
MAX_PATH
))
)
if
(
name
&&
(
len
=
strlenW
(
name
))
>
MAX_PATH
)
{
SetLastError
(
ERROR_FILENAME_EXCED_RANGE
);
return
0
;
...
...
@@ -498,7 +508,7 @@ static HANDLE FILE_OpenPipe(LPCSTR name, DWORD access)
{
req
->
access
=
access
;
SetLastError
(
0
);
wine_server_add_data
(
req
,
buffer
,
len
*
sizeof
(
WCHAR
)
);
wine_server_add_data
(
req
,
name
,
len
*
sizeof
(
WCHAR
)
);
wine_server_call_err
(
req
);
ret
=
reply
->
handle
;
}
...
...
@@ -508,7 +518,7 @@ static HANDLE FILE_OpenPipe(LPCSTR name, DWORD access)
}
/*************************************************************************
* CreateFile
A
[KERNEL32.@] Creates or opens a file or other object
* CreateFile
W
[KERNEL32.@] Creates or opens a file or other object
*
* Creates or opens an object, and returns a handle that can be used to
* access that object.
...
...
@@ -535,19 +545,24 @@ static HANDLE FILE_OpenPipe(LPCSTR name, DWORD access)
* Doesn't support character devices, template files, or a
* lot of the 'attributes' flags yet.
*/
HANDLE
WINAPI
CreateFile
A
(
LPC
STR
filename
,
DWORD
access
,
DWORD
sharing
,
HANDLE
WINAPI
CreateFile
W
(
LPCW
STR
filename
,
DWORD
access
,
DWORD
sharing
,
LPSECURITY_ATTRIBUTES
sa
,
DWORD
creation
,
DWORD
attributes
,
HANDLE
template
)
{
DOS_FULL_NAME
full_name
;
HANDLE
ret
;
static
const
WCHAR
bkslashes_with_question_markW
[]
=
{
'\\'
,
'\\'
,
'?'
,
'\\'
,
0
};
static
const
WCHAR
bkslashes_with_dotW
[]
=
{
'\\'
,
'\\'
,
'.'
,
'\\'
,
0
};
static
const
WCHAR
bkslashesW
[]
=
{
'\\'
,
'\\'
,
0
};
static
const
WCHAR
coninW
[]
=
{
'C'
,
'O'
,
'N'
,
'I'
,
'N'
,
'$'
,
0
};
static
const
WCHAR
conoutW
[]
=
{
'C'
,
'O'
,
'N'
,
'O'
,
'U'
,
'T'
,
'$'
,
0
};
if
(
!
filename
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
INVALID_HANDLE_VALUE
;
}
TRACE
(
"%s %s%s%s%s%s%s%s
\n
"
,
filename
,
TRACE
(
"%s %s%s%s%s%s%s%s
attributes 0x%lx
\n
"
,
debugstr_w
(
filename
)
,
((
access
&
GENERIC_READ
)
==
GENERIC_READ
)
?
"GENERIC_READ "
:
""
,
((
access
&
GENERIC_WRITE
)
==
GENERIC_WRITE
)
?
"GENERIC_WRITE "
:
""
,
(
!
access
)
?
"QUERY_ACCESS "
:
""
,
...
...
@@ -558,30 +573,33 @@ HANDLE WINAPI CreateFileA( LPCSTR filename, DWORD access, DWORD sharing,
(
creation
==
CREATE_ALWAYS
)
?
"CREATE_ALWAYS "
:
(
creation
==
OPEN_EXISTING
)
?
"OPEN_EXISTING "
:
(
creation
==
OPEN_ALWAYS
)
?
"OPEN_ALWAYS "
:
(
creation
==
TRUNCATE_EXISTING
)
?
"TRUNCATE_EXISTING "
:
""
);
(
creation
==
TRUNCATE_EXISTING
)
?
"TRUNCATE_EXISTING "
:
""
,
attributes
);
/* If the name starts with '\\?\', ignore the first 4 chars. */
if
(
!
strncmp
(
filename
,
"
\\\\
?
\\
"
,
4
))
if
(
!
strncmp
W
(
filename
,
bkslashes_with_question_markW
,
4
))
{
static
const
WCHAR
uncW
[]
=
{
'U'
,
'N'
,
'C'
,
'\\'
,
0
};
filename
+=
4
;
if
(
!
strncmp
(
filename
,
"UNC
\\
"
,
4
))
if
(
!
strncmp
iW
(
filename
,
uncW
,
4
))
{
FIXME
(
"UNC name (%s) not supported.
\n
"
,
filename
);
FIXME
(
"UNC name (%s) not supported.
\n
"
,
debugstr_w
(
filename
)
);
SetLastError
(
ERROR_PATH_NOT_FOUND
);
return
INVALID_HANDLE_VALUE
;
}
}
if
(
!
strncmp
(
filename
,
"
\\\\
.
\\
"
,
4
))
{
if
(
!
strncasecmp
(
&
filename
[
4
],
"pipe
\\
"
,
5
))
if
(
!
strncmpW
(
filename
,
bkslashes_with_dotW
,
4
))
{
static
const
WCHAR
pipeW
[]
=
{
'P'
,
'I'
,
'P'
,
'E'
,
'\\'
,
0
};
if
(
!
strncmpiW
(
filename
+
4
,
pipeW
,
5
))
{
TRACE
(
"Opening a pipe: %s
\n
"
,
filename
);
TRACE
(
"Opening a pipe: %s
\n
"
,
debugstr_w
(
filename
)
);
ret
=
FILE_OpenPipe
(
filename
,
access
);
goto
done
;
}
else
if
(
isalpha
(
filename
[
4
])
&&
filename
[
5
]
==
':'
&&
filename
[
6
]
==
'\0'
)
else
if
(
isalpha
W
(
filename
[
4
])
&&
filename
[
5
]
==
':'
&&
filename
[
6
]
==
'\0'
)
{
ret
=
FILE_CreateDevice
(
(
toupper
(
filename
[
4
])
-
'A'
)
|
0x20000
,
access
,
sa
);
ret
=
FILE_CreateDevice
(
(
toupper
W
(
filename
[
4
])
-
'A'
)
|
0x20000
,
access
,
sa
);
goto
done
;
}
else
if
(
!
DOSFS_GetDevice
(
filename
))
...
...
@@ -594,23 +612,23 @@ HANDLE WINAPI CreateFileA( LPCSTR filename, DWORD access, DWORD sharing,
}
/* If the name still starts with '\\', it's a UNC name. */
if
(
!
strncmp
(
filename
,
"
\\\\
"
,
2
))
if
(
!
strncmp
W
(
filename
,
bkslashesW
,
2
))
{
ret
=
SMB_CreateFile
A
(
filename
,
access
,
sharing
,
sa
,
creation
,
attributes
,
template
);
ret
=
SMB_CreateFile
W
(
filename
,
access
,
sharing
,
sa
,
creation
,
attributes
,
template
);
goto
done
;
}
/* If the name contains a DOS wild card (* or ?), do no create a file */
if
(
strchr
(
filename
,
'*'
)
||
strchr
(
filename
,
'?'
))
if
(
strchr
W
(
filename
,
'*'
)
||
strchrW
(
filename
,
'?'
))
return
INVALID_HANDLE_VALUE
;
/* Open a console for CONIN$ or CONOUT$ */
if
(
!
strc
asecmp
(
filename
,
"CONIN$"
))
if
(
!
strc
mpiW
(
filename
,
coninW
))
{
ret
=
FILE_OpenConsole
(
FALSE
,
access
,
sharing
,
sa
);
goto
done
;
}
if
(
!
strc
asecmp
(
filename
,
"CONOUT$"
))
if
(
!
strc
mpiW
(
filename
,
conoutW
))
{
ret
=
FILE_OpenConsole
(
TRUE
,
access
,
sharing
,
sa
);
goto
done
;
...
...
@@ -618,12 +636,12 @@ HANDLE WINAPI CreateFileA( LPCSTR filename, DWORD access, DWORD sharing,
if
(
DOSFS_GetDevice
(
filename
))
{
TRACE
(
"opening device
'%s'
\n
"
,
filename
);
TRACE
(
"opening device
%s
\n
"
,
debugstr_w
(
filename
)
);
if
(
!
(
ret
=
DOSFS_OpenDevice
(
filename
,
access
,
attributes
,
sa
)))
{
/* Do not silence this please. It is a critical error. -MM */
ERR
(
"Couldn't open device
'%s'!
\n
"
,
filename
);
ERR
(
"Couldn't open device
%s!
\n
"
,
debugstr_w
(
filename
)
);
SetLastError
(
ERROR_FILE_NOT_FOUND
);
}
goto
done
;
...
...
@@ -634,33 +652,48 @@ HANDLE WINAPI CreateFileA( LPCSTR filename, DWORD access, DWORD sharing,
(
creation
==
OPEN_EXISTING
)
||
(
creation
==
TRUNCATE_EXISTING
),
&
full_name
))
{
WARN
(
"Unable to get full filename from
'%s'
(GLE %ld)
\n
"
,
filename
,
GetLastError
());
WARN
(
"Unable to get full filename from
%s
(GLE %ld)
\n
"
,
debugstr_w
(
filename
)
,
GetLastError
());
return
INVALID_HANDLE_VALUE
;
}
ret
=
FILE_CreateFile
(
full_name
.
long_name
,
access
,
sharing
,
sa
,
creation
,
attributes
,
template
,
DRIVE_GetFlags
(
full_name
.
drive
)
&
DRIVE_FAIL_READ_ONLY
,
GetDriveType
A
(
full_name
.
short_name
)
);
GetDriveType
W
(
full_name
.
short_name
)
);
done:
if
(
!
ret
)
ret
=
INVALID_HANDLE_VALUE
;
TRACE
(
"returning %08x
\n
"
,
ret
);
return
ret
;
}
/*************************************************************************
* CreateFile
W
(KERNEL32.@)
* CreateFile
A
(KERNEL32.@)
*/
HANDLE
WINAPI
CreateFile
W
(
LPCW
STR
filename
,
DWORD
access
,
DWORD
sharing
,
HANDLE
WINAPI
CreateFile
A
(
LPC
STR
filename
,
DWORD
access
,
DWORD
sharing
,
LPSECURITY_ATTRIBUTES
sa
,
DWORD
creation
,
DWORD
attributes
,
HANDLE
template
)
{
LPSTR
afn
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
filename
);
HANDLE
res
=
CreateFileA
(
afn
,
access
,
sharing
,
sa
,
creation
,
attributes
,
template
);
HeapFree
(
GetProcessHeap
(),
0
,
afn
);
return
res
;
UNICODE_STRING
filenameW
;
HANDLE
ret
=
INVALID_HANDLE_VALUE
;
if
(
!
filename
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
INVALID_HANDLE_VALUE
;
}
if
(
RtlCreateUnicodeStringFromAsciiz
(
&
filenameW
,
filename
))
{
ret
=
CreateFileW
(
filenameW
.
Buffer
,
access
,
sharing
,
sa
,
creation
,
attributes
,
template
);
RtlFreeUnicodeString
(
&
filenameW
);
}
else
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
ret
;
}
...
...
@@ -735,6 +768,8 @@ DWORD WINAPI GetFileInformationByHandle( HANDLE hFile,
DWORD
ret
;
if
(
!
info
)
return
0
;
TRACE
(
"%08x
\n
"
,
hFile
);
SERVER_START_REQ
(
get_file_info
)
{
req
->
handle
=
hFile
;
...
...
@@ -780,9 +815,9 @@ DWORD WINAPI GetFileAttributes16( LPCSTR name )
/**************************************************************************
* GetFileAttributes
A
(KERNEL32.@)
* GetFileAttributes
W
(KERNEL32.@)
*/
DWORD
WINAPI
GetFileAttributes
A
(
LPC
STR
name
)
DWORD
WINAPI
GetFileAttributes
W
(
LPCW
STR
name
)
{
DOS_FULL_NAME
full_name
;
BY_HANDLE_FILE_INFORMATION
info
;
...
...
@@ -800,14 +835,27 @@ DWORD WINAPI GetFileAttributesA( LPCSTR name )
/**************************************************************************
* GetFileAttributes
W
(KERNEL32.@)
* GetFileAttributes
A
(KERNEL32.@)
*/
DWORD
WINAPI
GetFileAttributes
W
(
LPCW
STR
name
)
DWORD
WINAPI
GetFileAttributes
A
(
LPC
STR
name
)
{
LPSTR
nameA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
name
);
DWORD
res
=
GetFileAttributesA
(
nameA
);
HeapFree
(
GetProcessHeap
(),
0
,
nameA
);
return
res
;
UNICODE_STRING
nameW
;
DWORD
ret
=
(
DWORD
)
-
1
;
if
(
!
name
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
(
DWORD
)
-
1
;
}
if
(
RtlCreateUnicodeStringFromAsciiz
(
&
nameW
,
name
))
{
ret
=
GetFileAttributesW
(
nameW
.
Buffer
);
RtlFreeUnicodeString
(
&
nameW
);
}
else
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
ret
;
}
...
...
@@ -821,17 +869,24 @@ BOOL16 WINAPI SetFileAttributes16( LPCSTR lpFileName, DWORD attributes )
/**************************************************************************
* SetFileAttributes
A
(KERNEL32.@)
* SetFileAttributes
W
(KERNEL32.@)
*/
BOOL
WINAPI
SetFileAttributes
A
(
LPC
STR
lpFileName
,
DWORD
attributes
)
BOOL
WINAPI
SetFileAttributes
W
(
LPCW
STR
lpFileName
,
DWORD
attributes
)
{
struct
stat
buf
;
DOS_FULL_NAME
full_name
;
if
(
!
lpFileName
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
TRACE
(
"(%s,%lx)
\n
"
,
debugstr_w
(
lpFileName
),
attributes
);
if
(
!
DOSFS_GetFullName
(
lpFileName
,
TRUE
,
&
full_name
))
return
FALSE
;
TRACE
(
"(%s,%lx)
\n
"
,
lpFileName
,
attributes
);
if
(
stat
(
full_name
.
long_name
,
&
buf
)
==-
1
)
{
FILE_SetDosError
();
...
...
@@ -854,16 +909,17 @@ BOOL WINAPI SetFileAttributesA(LPCSTR lpFileName, DWORD attributes)
if
(
attributes
&
FILE_ATTRIBUTE_DIRECTORY
)
{
if
(
!
S_ISDIR
(
buf
.
st_mode
))
FIXME
(
"SetFileAttributes expected the file
'%s'
to be a directory
\n
"
,
lpFileName
);
FIXME
(
"SetFileAttributes expected the file
%s
to be a directory
\n
"
,
debugstr_w
(
lpFileName
)
);
attributes
&=
~
FILE_ATTRIBUTE_DIRECTORY
;
}
attributes
&=
~
(
FILE_ATTRIBUTE_NORMAL
|
FILE_ATTRIBUTE_ARCHIVE
|
FILE_ATTRIBUTE_HIDDEN
|
FILE_ATTRIBUTE_SYSTEM
);
if
(
attributes
)
FIXME
(
"(%s):%lx attribute(s) not implemented.
\n
"
,
lpFileName
,
attributes
);
FIXME
(
"(%s):%lx attribute(s) not implemented.
\n
"
,
debugstr_w
(
lpFileName
),
attributes
);
if
(
-
1
==
chmod
(
full_name
.
long_name
,
buf
.
st_mode
))
{
if
(
GetDriveTypeA
(
lpFileName
)
==
DRIVE_CDROM
)
{
if
(
GetDriveTypeW
(
lpFileName
)
==
DRIVE_CDROM
)
{
SetLastError
(
ERROR_ACCESS_DENIED
);
return
FALSE
;
}
...
...
@@ -886,18 +942,27 @@ BOOL WINAPI SetFileAttributesA(LPCSTR lpFileName, DWORD attributes)
/**************************************************************************
* SetFileAttributes
W
(KERNEL32.@)
* SetFileAttributes
A
(KERNEL32.@)
*/
BOOL
WINAPI
SetFileAttributes
W
(
LPCW
STR
lpFileName
,
DWORD
attributes
)
BOOL
WINAPI
SetFileAttributes
A
(
LPC
STR
lpFileName
,
DWORD
attributes
)
{
BOOL
res
;
DWORD
len
=
WideCharToMultiByte
(
CP_ACP
,
0
,
lpFileName
,
-
1
,
NULL
,
0
,
NULL
,
NULL
);
LPSTR
afn
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
);
UNICODE_STRING
filenameW
;
HANDLE
ret
=
FALSE
;
if
(
!
lpFileName
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
WideCharToMultiByte
(
CP_ACP
,
0
,
lpFileName
,
-
1
,
afn
,
len
,
NULL
,
NULL
);
res
=
SetFileAttributesA
(
afn
,
attributes
);
HeapFree
(
GetProcessHeap
(),
0
,
afn
);
return
res
;
if
(
RtlCreateUnicodeStringFromAsciiz
(
&
filenameW
,
lpFileName
))
{
ret
=
SetFileAttributesW
(
filenameW
.
Buffer
,
attributes
);
RtlFreeUnicodeString
(
&
filenameW
);
}
else
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
ret
;
}
...
...
@@ -949,30 +1014,36 @@ INT WINAPI CompareFileTime( LPFILETIME x, LPFILETIME y )
/***********************************************************************
* FILE_GetTempFileName : utility for GetTempFileName
*/
static
UINT
FILE_GetTempFileName
(
LPC
STR
path
,
LPC
STR
prefix
,
UINT
unique
,
LP
STR
buffer
,
BOOL
isWin16
)
static
UINT
FILE_GetTempFileName
(
LPC
WSTR
path
,
LPCW
STR
prefix
,
UINT
unique
,
LP
WSTR
buffer
)
{
static
UINT
unique_temp
;
DOS_FULL_NAME
full_name
;
int
i
;
LPSTR
p
;
LP
W
STR
p
;
UINT
num
;
char
buf
[
20
];
if
(
!
path
||
!
prefix
||
!
buffer
)
return
0
;
if
(
!
path
||
!
prefix
||
!
buffer
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
0
;
}
if
(
!
unique_temp
)
unique_temp
=
time
(
NULL
)
&
0xffff
;
num
=
unique
?
(
unique
&
0xffff
)
:
(
unique_temp
++
&
0xffff
);
strcpy
(
buffer
,
path
);
p
=
buffer
+
strlen
(
buffer
);
strcpy
W
(
buffer
,
path
);
p
=
buffer
+
strlen
W
(
buffer
);
/* add a \, if there isn't one and path is more than just the drive letter ... */
if
(
!
((
strlen
(
buffer
)
==
2
)
&&
(
buffer
[
1
]
==
':'
))
if
(
!
((
strlen
W
(
buffer
)
==
2
)
&&
(
buffer
[
1
]
==
':'
))
&&
((
p
==
buffer
)
||
(
p
[
-
1
]
!=
'\\'
)))
*
p
++
=
'\\'
;
if
(
isWin16
)
*
p
++
=
'~'
;
for
(
i
=
3
;
(
i
>
0
)
&&
(
*
prefix
);
i
--
)
*
p
++
=
*
prefix
++
;
sprintf
(
p
,
"%04x.tmp"
,
num
);
sprintf
(
buf
,
"%04x.tmp"
,
num
);
MultiByteToWideChar
(
CP_ACP
,
0
,
buf
,
-
1
,
p
,
20
);
/* Now try to create it */
...
...
@@ -980,19 +1051,19 @@ static UINT FILE_GetTempFileName( LPCSTR path, LPCSTR prefix, UINT unique,
{
do
{
HANDLE
handle
=
CreateFile
A
(
buffer
,
GENERIC_WRITE
,
0
,
NULL
,
HANDLE
handle
=
CreateFile
W
(
buffer
,
GENERIC_WRITE
,
0
,
NULL
,
CREATE_NEW
,
FILE_ATTRIBUTE_NORMAL
,
0
);
if
(
handle
!=
INVALID_HANDLE_VALUE
)
{
/* We created it */
TRACE
(
"created %s
\n
"
,
buffer
);
TRACE
(
"created %s
\n
"
,
debugstr_w
(
buffer
)
);
CloseHandle
(
handle
);
break
;
}
if
(
GetLastError
()
!=
ERROR_FILE_EXISTS
)
break
;
/* No need to go on */
num
++
;
sprintf
(
p
,
"%04x.tmp"
,
num
);
sprintf
(
buf
,
"%04x.tmp"
,
num
);
MultiByteToWideChar
(
CP_ACP
,
0
,
buf
,
-
1
,
p
,
20
);
}
while
(
num
!=
(
unique
&
0xffff
));
}
...
...
@@ -1000,13 +1071,14 @@ static UINT FILE_GetTempFileName( LPCSTR path, LPCSTR prefix, UINT unique,
if
(
DOSFS_GetFullName
(
buffer
,
FALSE
,
&
full_name
))
{
char
*
slash
;
/* Check if we have write access in the directory */
if
((
p
=
strrchr
(
full_name
.
long_name
,
'/'
)))
*
p
=
'\0'
;
if
((
slash
=
strrchr
(
full_name
.
long_name
,
'/'
)))
*
slash
=
'\0'
;
if
(
access
(
full_name
.
long_name
,
W_OK
)
==
-
1
)
WARN
(
"returns
'%s'
, which doesn't seem to be writeable.
\n
"
,
buffer
);
WARN
(
"returns
%s
, which doesn't seem to be writeable.
\n
"
,
debugstr_w
(
buffer
)
);
}
TRACE
(
"returning %s
\n
"
,
buffer
);
TRACE
(
"returning %s
\n
"
,
debugstr_w
(
buffer
)
);
return
unique
?
unique
:
num
;
}
...
...
@@ -1017,7 +1089,26 @@ static UINT FILE_GetTempFileName( LPCSTR path, LPCSTR prefix, UINT unique,
UINT
WINAPI
GetTempFileNameA
(
LPCSTR
path
,
LPCSTR
prefix
,
UINT
unique
,
LPSTR
buffer
)
{
return
FILE_GetTempFileName
(
path
,
prefix
,
unique
,
buffer
,
FALSE
);
UNICODE_STRING
pathW
,
prefixW
;
WCHAR
bufferW
[
MAX_PATH
];
UINT
ret
;
if
(
!
path
||
!
prefix
||
!
buffer
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
0
;
}
RtlCreateUnicodeStringFromAsciiz
(
&
pathW
,
path
);
RtlCreateUnicodeStringFromAsciiz
(
&
prefixW
,
prefix
);
ret
=
GetTempFileNameW
(
pathW
.
Buffer
,
prefixW
.
Buffer
,
unique
,
bufferW
);
if
(
ret
)
WideCharToMultiByte
(
CP_ACP
,
0
,
bufferW
,
-
1
,
buffer
,
MAX_PATH
,
NULL
,
NULL
);
RtlFreeUnicodeString
(
&
pathW
);
RtlFreeUnicodeString
(
&
prefixW
);
return
ret
;
}
/***********************************************************************
...
...
@@ -1026,18 +1117,7 @@ UINT WINAPI GetTempFileNameA( LPCSTR path, LPCSTR prefix, UINT unique,
UINT
WINAPI
GetTempFileNameW
(
LPCWSTR
path
,
LPCWSTR
prefix
,
UINT
unique
,
LPWSTR
buffer
)
{
LPSTR
patha
,
prefixa
;
char
buffera
[
144
];
UINT
ret
;
if
(
!
path
)
return
0
;
patha
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
path
);
prefixa
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
prefix
);
ret
=
FILE_GetTempFileName
(
patha
,
prefixa
,
unique
,
buffera
,
FALSE
);
MultiByteToWideChar
(
CP_ACP
,
0
,
buffera
,
-
1
,
buffer
,
MAX_PATH
);
HeapFree
(
GetProcessHeap
(),
0
,
patha
);
HeapFree
(
GetProcessHeap
(),
0
,
prefixa
);
return
ret
;
return
FILE_GetTempFileName
(
path
,
prefix
,
unique
,
buffer
);
}
...
...
@@ -1047,7 +1127,9 @@ UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, UINT unique,
UINT16
WINAPI
GetTempFileName16
(
BYTE
drive
,
LPCSTR
prefix
,
UINT16
unique
,
LPSTR
buffer
)
{
char
temppath
[
144
];
char
temppath
[
MAX_PATH
];
char
*
prefix16
=
NULL
;
UINT16
ret
;
if
(
!
(
drive
&
~
TF_FORCEDRIVE
))
/* drive 0 means current default drive */
drive
|=
DRIVE_GetCurrentDrive
()
+
'A'
;
...
...
@@ -1062,8 +1144,19 @@ UINT16 WINAPI GetTempFileName16( BYTE drive, LPCSTR prefix, UINT16 unique,
if
(
drive
&
TF_FORCEDRIVE
)
sprintf
(
temppath
,
"%c:"
,
drive
&
~
TF_FORCEDRIVE
);
else
GetTempPathA
(
132
,
temppath
);
return
(
UINT16
)
FILE_GetTempFileName
(
temppath
,
prefix
,
unique
,
buffer
,
TRUE
);
GetTempPathA
(
MAX_PATH
,
temppath
);
if
(
prefix
)
{
prefix16
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlen
(
prefix
)
+
2
);
*
prefix16
=
'~'
;
strcpy
(
prefix16
+
1
,
prefix
);
}
ret
=
GetTempFileNameA
(
temppath
,
prefix16
,
unique
,
buffer
);
if
(
prefix16
)
HeapFree
(
GetProcessHeap
(),
0
,
prefix16
);
return
ret
;
}
/***********************************************************************
...
...
@@ -1080,7 +1173,9 @@ static HFILE FILE_DoOpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode,
WORD
filedatetime
[
2
];
DOS_FULL_NAME
full_name
;
DWORD
access
,
sharing
;
char
*
p
;
WCHAR
*
p
;
WCHAR
buffer
[
MAX_PATH
];
LPWSTR
nameW
;
if
(
!
ofs
)
return
HFILE_ERROR
;
...
...
@@ -1146,28 +1241,31 @@ static HFILE FILE_DoOpenFile( LPCSTR name, OFSTRUCT *ofs, UINT mode,
goto
success
;
}
MultiByteToWideChar
(
CP_ACP
,
0
,
name
,
-
1
,
buffer
,
MAX_PATH
);
nameW
=
buffer
;
/* If OF_SEARCH is set, ignore the given path */
if
((
mode
&
OF_SEARCH
)
&&
!
(
mode
&
OF_REOPEN
))
{
/* First try the file name as is */
if
(
DOSFS_GetFullName
(
name
,
TRUE
,
&
full_name
))
goto
found
;
if
(
DOSFS_GetFullName
(
name
W
,
TRUE
,
&
full_name
))
goto
found
;
/* Now remove the path */
if
(
name
[
0
]
&&
(
name
[
1
]
==
':'
))
name
+=
2
;
if
((
p
=
strrchr
(
name
,
'\\'
)))
name
=
p
+
1
;
if
((
p
=
strrchr
(
name
,
'/'
)))
name
=
p
+
1
;
if
(
!
name
[
0
])
goto
not_found
;
if
(
name
W
[
0
]
&&
(
nameW
[
1
]
==
':'
))
nameW
+=
2
;
if
((
p
=
strrchr
W
(
nameW
,
'\\'
)))
nameW
=
p
+
1
;
if
((
p
=
strrchr
W
(
nameW
,
'/'
)))
nameW
=
p
+
1
;
if
(
!
name
W
[
0
])
goto
not_found
;
}
/* Now look for the file */
if
(
!
DIR_SearchPath
(
NULL
,
name
,
NULL
,
&
full_name
,
win32
))
goto
not_found
;
if
(
!
DIR_SearchPath
(
NULL
,
name
W
,
NULL
,
&
full_name
,
win32
))
goto
not_found
;
found:
TRACE
(
"found %s = %s
\n
"
,
full_name
.
long_name
,
full_name
.
short_name
);
lstrcpynA
(
ofs
->
szPathName
,
full_name
.
short_name
,
sizeof
(
ofs
->
szPathName
)
);
full_name
.
long_name
,
debugstr_w
(
full_name
.
short_name
)
);
WideCharToMultiByte
(
CP_ACP
,
0
,
full_name
.
short_name
,
-
1
,
ofs
->
szPathName
,
sizeof
(
ofs
->
szPathName
),
NULL
,
NULL
);
if
(
mode
&
OF_SHARE_EXCLUSIVE
)
/* Some InstallShield version uses OF_SHARE_EXCLUSIVE
...
...
@@ -1199,9 +1297,9 @@ found:
}
handle
=
FILE_CreateFile
(
full_name
.
long_name
,
access
,
sharing
,
NULL
,
OPEN_EXISTING
,
0
,
0
,
DRIVE_GetFlags
(
full_name
.
drive
)
&
DRIVE_FAIL_READ_ONLY
,
GetDriveTypeA
(
full_name
.
short_name
)
);
NULL
,
OPEN_EXISTING
,
0
,
0
,
DRIVE_GetFlags
(
full_name
.
drive
)
&
DRIVE_FAIL_READ_ONLY
,
GetDriveTypeW
(
full_name
.
short_name
)
);
if
(
!
handle
)
goto
not_found
;
GetFileTime
(
handle
,
NULL
,
NULL
,
&
filetime
);
...
...
@@ -1706,13 +1804,17 @@ BOOL WINAPI ReadFile( HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
default:
if
(
unix_handle
==
-
1
)
return
FALSE
;
if
(
overlapped
)
}
if
(
overlapped
)
{
off_t
offset
=
OVERLAPPED_OFFSET
(
overlapped
);
if
(
lseek
(
unix_handle
,
offset
,
SEEK_SET
)
==
-
1
)
{
close
(
unix_handle
);
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
break
;
}
/* code for synchronous reads */
...
...
@@ -1930,6 +2032,17 @@ BOOL WINAPI WriteFile( HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
break
;
}
if
(
overlapped
)
{
off_t
offset
=
OVERLAPPED_OFFSET
(
overlapped
);
if
(
lseek
(
unix_handle
,
offset
,
SEEK_SET
)
==
-
1
)
{
close
(
unix_handle
);
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
}
/* synchronous file write */
while
((
result
=
write
(
unix_handle
,
buffer
,
bytesToWrite
))
==
-
1
)
{
...
...
@@ -2224,9 +2337,9 @@ BOOL16 WINAPI DeleteFile16( LPCSTR path )
/***********************************************************************
* DeleteFile
A
(KERNEL32.@)
* DeleteFile
W
(KERNEL32.@)
*/
BOOL
WINAPI
DeleteFile
A
(
LPC
STR
path
)
BOOL
WINAPI
DeleteFile
W
(
LPCW
STR
path
)
{
DOS_FULL_NAME
full_name
;
HANDLE
hFile
;
...
...
@@ -2236,7 +2349,7 @@ BOOL WINAPI DeleteFileA( LPCSTR path )
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
TRACE
(
"
'%s'
\n
"
,
path
);
TRACE
(
"
%s
\n
"
,
debugstr_w
(
path
)
);
if
(
!*
path
)
{
...
...
@@ -2245,7 +2358,7 @@ BOOL WINAPI DeleteFileA( LPCSTR path )
}
if
(
DOSFS_GetDevice
(
path
))
{
WARN
(
"cannot remove DOS device
'%s'!
\n
"
,
path
);
WARN
(
"cannot remove DOS device
%s!
\n
"
,
debugstr_w
(
path
)
);
SetLastError
(
ERROR_FILE_NOT_FOUND
);
return
FALSE
;
}
...
...
@@ -2255,7 +2368,7 @@ BOOL WINAPI DeleteFileA( LPCSTR path )
/* check if we are allowed to delete the source */
hFile
=
FILE_CreateFile
(
full_name
.
long_name
,
GENERIC_READ
|
GENERIC_WRITE
,
0
,
NULL
,
OPEN_EXISTING
,
0
,
0
,
TRUE
,
GetDriveType
A
(
full_name
.
short_name
)
);
GetDriveType
W
(
full_name
.
short_name
)
);
if
(
!
hFile
)
return
FALSE
;
if
(
unlink
(
full_name
.
long_name
)
==
-
1
)
...
...
@@ -2270,13 +2383,26 @@ BOOL WINAPI DeleteFileA( LPCSTR path )
/***********************************************************************
* DeleteFile
W
(KERNEL32.@)
* DeleteFile
A
(KERNEL32.@)
*/
BOOL
WINAPI
DeleteFile
W
(
LPCW
STR
path
)
BOOL
WINAPI
DeleteFile
A
(
LPC
STR
path
)
{
LPSTR
xpath
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
path
);
BOOL
ret
=
DeleteFileA
(
xpath
);
HeapFree
(
GetProcessHeap
(),
0
,
xpath
);
UNICODE_STRING
pathW
;
BOOL
ret
=
FALSE
;
if
(
!
path
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
if
(
RtlCreateUnicodeStringFromAsciiz
(
&
pathW
,
path
))
{
ret
=
DeleteFileW
(
pathW
.
Buffer
);
RtlFreeUnicodeString
(
&
pathW
);
}
else
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
ret
;
}
...
...
@@ -2339,16 +2465,18 @@ inline static BOOL is_executable( const char *name )
* [0] <- indicates end of strings
*
*/
static
BOOL
FILE_AddBootRenameEntry
(
const
char
*
fn1
,
const
char
*
fn2
,
DWORD
flags
)
static
BOOL
FILE_AddBootRenameEntry
(
LPCWSTR
fn1
,
LPCWSTR
fn2
,
DWORD
flags
)
{
static
const
char
PreString
[]
=
"
\\
??
\\
"
;
static
const
char
ValueName
[]
=
"PendingFileRenameOperations"
;
static
const
WCHAR
PreString
[]
=
{
'\\'
,
'?'
,
'?'
,
'\\'
,
0
};
static
const
WCHAR
ValueName
[]
=
{
'P'
,
'e'
,
'n'
,
'd'
,
'i'
,
'n'
,
'g'
,
'F'
,
'i'
,
'l'
,
'e'
,
'R'
,
'e'
,
'n'
,
'a'
,
'm'
,
'e'
,
'O'
,
'p'
,
'e'
,
'r'
,
'a'
,
't'
,
'i'
,
'o'
,
'n'
,
's'
,
0
};
BOOL
rc
=
FALSE
;
HKEY
Reboot
=
0
;
DWORD
Type
,
len
1
,
len2
,
l
;
DWORD
Type
,
len
0
,
len1
,
len2
;
DWORD
DataSize
=
0
;
BYTE
*
Buffer
=
NULL
;
WCHAR
*
p
;
if
(
RegCreateKeyA
(
HKEY_LOCAL_MACHINE
,
"SYSTEM
\\
CurrentControlSet
\\
Control
\\
Session Manager"
,
&
Reboot
)
!=
ERROR_SUCCESS
)
...
...
@@ -2358,41 +2486,60 @@ static BOOL FILE_AddBootRenameEntry( const char *fn1, const char *fn2, DWORD fla
return
FALSE
;
}
l
=
strlen
(
PreString
);
len1
=
strlen
(
fn1
)
+
l
+
1
;
l
en0
=
strlenW
(
PreString
);
len1
=
strlen
W
(
fn1
)
+
len0
+
1
;
if
(
fn2
)
{
len2
=
strlen
(
fn2
)
+
l
+
1
;
len2
=
strlen
W
(
fn2
)
+
len0
+
1
;
if
(
flags
&
MOVEFILE_REPLACE_EXISTING
)
len2
++
;
/* Plus 1 because of the leading '!' */
}
else
len2
=
1
;
/* minimum is the 0 byte for the empty second string */
else
len2
=
1
;
/* minimum is the 0 characters for the empty second string */
/* convert characters to bytes */
len0
*=
sizeof
(
WCHAR
);
len1
*=
sizeof
(
WCHAR
);
len2
*=
sizeof
(
WCHAR
);
/* First we check if the key exists and if so how many bytes it already contains. */
if
(
RegQueryValueEx
A
(
Reboot
,
ValueName
,
NULL
,
&
Type
,
NULL
,
&
DataSize
)
==
ERROR_SUCCESS
)
if
(
RegQueryValueEx
W
(
Reboot
,
ValueName
,
NULL
,
&
Type
,
NULL
,
&
DataSize
)
==
ERROR_SUCCESS
)
{
if
(
Type
!=
REG_MULTI_SZ
)
goto
Quit
;
if
(
!
(
Buffer
=
HeapAlloc
(
GetProcessHeap
(),
0
,
DataSize
+
len1
+
len2
+
1
)))
goto
Quit
;
if
(
RegQueryValueEx
A
(
Reboot
,
ValueName
,
NULL
,
&
Type
,
Buffer
,
&
DataSize
)
!=
ERROR_SUCCESS
)
if
(
!
(
Buffer
=
HeapAlloc
(
GetProcessHeap
(),
0
,
DataSize
+
len1
+
len2
+
sizeof
(
WCHAR
)
)))
goto
Quit
;
if
(
RegQueryValueEx
W
(
Reboot
,
ValueName
,
NULL
,
&
Type
,
Buffer
,
&
DataSize
)
!=
ERROR_SUCCESS
)
goto
Quit
;
if
(
DataSize
)
DataSize
--
;
/* remove terminating null (will be added back later) */
if
(
DataSize
)
DataSize
-=
sizeof
(
WCHAR
)
;
/* remove terminating null (will be added back later) */
}
else
{
if
(
!
(
Buffer
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len1
+
len2
+
1
)))
goto
Quit
;
if
(
!
(
Buffer
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len1
+
len2
+
sizeof
(
WCHAR
)
)))
goto
Quit
;
DataSize
=
0
;
}
sprintf
(
Buffer
+
DataSize
,
"%s%s"
,
PreString
,
fn1
);
p
=
(
WCHAR
*
)(
Buffer
+
DataSize
);
strcpyW
(
p
,
PreString
);
strcatW
(
p
,
fn1
);
DataSize
+=
len1
;
if
(
fn2
)
{
sprintf
(
Buffer
+
DataSize
,
"%s%s%s"
,
(
flags
&
MOVEFILE_REPLACE_EXISTING
)
?
"!"
:
""
,
PreString
,
fn2
);
p
=
(
WCHAR
*
)(
Buffer
+
DataSize
);
if
(
flags
&
MOVEFILE_REPLACE_EXISTING
)
*
p
++
=
'!'
;
strcpyW
(
p
,
PreString
);
strcatW
(
p
,
fn2
);
DataSize
+=
len2
;
}
else
Buffer
[
DataSize
++
]
=
0
;
else
{
p
=
(
WCHAR
*
)(
Buffer
+
DataSize
);
*
p
=
0
;
DataSize
+=
sizeof
(
WCHAR
);
}
Buffer
[
DataSize
++
]
=
0
;
/* add final null */
rc
=
!
RegSetValueExA
(
Reboot
,
ValueName
,
0
,
REG_MULTI_SZ
,
Buffer
,
DataSize
);
/* add final null */
p
=
(
WCHAR
*
)(
Buffer
+
DataSize
);
*
p
=
0
;
DataSize
+=
sizeof
(
WCHAR
);
rc
=
!
RegSetValueExW
(
Reboot
,
ValueName
,
0
,
REG_MULTI_SZ
,
Buffer
,
DataSize
);
Quit:
if
(
Reboot
)
RegCloseKey
(
Reboot
);
...
...
@@ -2402,14 +2549,14 @@ static BOOL FILE_AddBootRenameEntry( const char *fn1, const char *fn2, DWORD fla
/**************************************************************************
* MoveFileEx
A
(KERNEL32.@)
* MoveFileEx
W
(KERNEL32.@)
*/
BOOL
WINAPI
MoveFileEx
A
(
LPCSTR
fn1
,
LPC
STR
fn2
,
DWORD
flag
)
BOOL
WINAPI
MoveFileEx
W
(
LPCWSTR
fn1
,
LPCW
STR
fn2
,
DWORD
flag
)
{
DOS_FULL_NAME
full_name1
,
full_name2
;
HANDLE
hFile
;
TRACE
(
"(%s,%s,%04lx)
\n
"
,
fn1
,
fn2
,
flag
);
TRACE
(
"(%s,%s,%04lx)
\n
"
,
debugstr_w
(
fn1
),
debugstr_w
(
fn2
)
,
flag
);
/* FIXME: <Gerhard W. Gruber>sparhawk@gmx.at
In case of W9x and lesser this function should return 120 (ERROR_CALL_NOT_IMPLEMENTED)
...
...
@@ -2471,15 +2618,15 @@ BOOL WINAPI MoveFileExA( LPCSTR fn1, LPCSTR fn2, DWORD flag )
Perhaps we should queue these command and execute it
when exiting... What about using on_exit(2)
*/
FIXME
(
"Please move existing file
'%s' to file '%s'
when Wine has finished
\n
"
,
fn1
,
fn2
);
FIXME
(
"Please move existing file
%s to file %s
when Wine has finished
\n
"
,
debugstr_w
(
fn1
),
debugstr_w
(
fn2
)
);
return
FILE_AddBootRenameEntry
(
fn1
,
fn2
,
flag
);
}
/* check if we are allowed to
delet
e the source */
hFile
=
FILE_CreateFile
(
full_name1
.
long_name
,
GENERIC_READ
|
GENERIC_WRITE
,
0
,
/* check if we are allowed to
renam
e the source */
hFile
=
FILE_CreateFile
(
full_name1
.
long_name
,
0
,
0
,
NULL
,
OPEN_EXISTING
,
0
,
0
,
TRUE
,
GetDriveType
A
(
full_name1
.
short_name
)
);
GetDriveType
W
(
full_name1
.
short_name
)
);
if
(
!
hFile
)
return
FALSE
;
CloseHandle
(
hFile
);
...
...
@@ -2487,7 +2634,7 @@ BOOL WINAPI MoveFileExA( LPCSTR fn1, LPCSTR fn2, DWORD flag )
** (but the file not being there is fine) */
hFile
=
FILE_CreateFile
(
full_name2
.
long_name
,
GENERIC_READ
|
GENERIC_WRITE
,
0
,
NULL
,
OPEN_EXISTING
,
0
,
0
,
TRUE
,
GetDriveType
A
(
full_name2
.
short_name
)
);
GetDriveType
W
(
full_name2
.
short_name
)
);
if
(
!
hFile
&&
GetLastError
()
!=
ERROR_FILE_NOT_FOUND
)
return
FALSE
;
CloseHandle
(
hFile
);
...
...
@@ -2500,7 +2647,7 @@ BOOL WINAPI MoveFileExA( LPCSTR fn1, LPCSTR fn2, DWORD flag )
SetLastError
(
ERROR_FILE_EXISTS
);
return
FALSE
;
}
return
CopyFile
A
(
fn1
,
fn2
,
!
(
flag
&
MOVEFILE_REPLACE_EXISTING
)
);
return
CopyFile
W
(
fn1
,
fn2
,
!
(
flag
&
MOVEFILE_REPLACE_EXISTING
)
);
}
if
(
rename
(
full_name1
.
long_name
,
full_name2
.
long_name
)
==
-
1
)
{
...
...
@@ -2535,7 +2682,7 @@ BOOL WINAPI MoveFileExA( LPCSTR fn1, LPCSTR fn2, DWORD flag )
Perhaps we should queue these command and execute it
when exiting... What about using on_exit(2)
*/
FIXME
(
"Please delete file
'%s' when Wine has finished
\n
"
,
fn1
);
FIXME
(
"Please delete file
%s when Wine has finished
\n
"
,
debugstr_w
(
fn1
)
);
return
FILE_AddBootRenameEntry
(
fn1
,
NULL
,
flag
);
}
...
...
@@ -2549,30 +2696,48 @@ BOOL WINAPI MoveFileExA( LPCSTR fn1, LPCSTR fn2, DWORD flag )
}
/**************************************************************************
* MoveFileEx
W
(KERNEL32.@)
* MoveFileEx
A
(KERNEL32.@)
*/
BOOL
WINAPI
MoveFileEx
W
(
LPCWSTR
fn1
,
LPCW
STR
fn2
,
DWORD
flag
)
BOOL
WINAPI
MoveFileEx
A
(
LPCSTR
fn1
,
LPC
STR
fn2
,
DWORD
flag
)
{
LPSTR
afn1
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
fn1
);
LPSTR
afn2
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
fn2
);
BOOL
res
=
MoveFileExA
(
afn1
,
afn2
,
flag
);
HeapFree
(
GetProcessHeap
(),
0
,
afn1
);
HeapFree
(
GetProcessHeap
(),
0
,
afn2
);
return
res
;
UNICODE_STRING
fn1W
,
fn2W
;
BOOL
ret
;
if
(
!
fn1
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
RtlCreateUnicodeStringFromAsciiz
(
&
fn1W
,
fn1
);
if
(
fn2
)
RtlCreateUnicodeStringFromAsciiz
(
&
fn2W
,
fn2
);
else
fn2W
.
Buffer
=
NULL
;
ret
=
MoveFileExW
(
fn1W
.
Buffer
,
fn2W
.
Buffer
,
flag
);
RtlFreeUnicodeString
(
&
fn1W
);
RtlFreeUnicodeString
(
&
fn2W
);
return
ret
;
}
/**************************************************************************
* MoveFile
A
(KERNEL32.@)
* MoveFile
W
(KERNEL32.@)
*
* Move file or directory
*/
BOOL
WINAPI
MoveFile
A
(
LPCSTR
fn1
,
LPC
STR
fn2
)
BOOL
WINAPI
MoveFile
W
(
LPCWSTR
fn1
,
LPCW
STR
fn2
)
{
DOS_FULL_NAME
full_name1
,
full_name2
;
struct
stat
fstat
;
TRACE
(
"(%s,%s)
\n
"
,
fn1
,
fn2
);
if
(
!
fn1
||
!
fn2
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
TRACE
(
"(%s,%s)
\n
"
,
debugstr_w
(
fn1
),
debugstr_w
(
fn2
)
);
if
(
!
DOSFS_GetFullName
(
fn1
,
TRUE
,
&
full_name1
))
return
FALSE
;
if
(
DOSFS_GetFullName
(
fn2
,
TRUE
,
&
full_name2
))
{
...
...
@@ -2583,7 +2748,7 @@ BOOL WINAPI MoveFileA( LPCSTR fn1, LPCSTR fn2 )
if
(
!
DOSFS_GetFullName
(
fn2
,
FALSE
,
&
full_name2
))
return
FALSE
;
if
(
full_name1
.
drive
==
full_name2
.
drive
)
/* move */
return
MoveFileEx
A
(
fn1
,
fn2
,
MOVEFILE_COPY_ALLOWED
);
return
MoveFileEx
W
(
fn1
,
fn2
,
MOVEFILE_COPY_ALLOWED
);
/* copy */
if
(
stat
(
full_name1
.
long_name
,
&
fstat
))
...
...
@@ -2599,57 +2764,81 @@ BOOL WINAPI MoveFileA( LPCSTR fn1, LPCSTR fn2 )
SetLastError
(
ERROR_GEN_FAILURE
);
return
FALSE
;
}
return
CopyFile
A
(
fn1
,
fn2
,
TRUE
);
/*fail, if exist */
return
CopyFile
W
(
fn1
,
fn2
,
TRUE
);
/*fail, if exist */
}
/**************************************************************************
* MoveFile
W
(KERNEL32.@)
* MoveFile
A
(KERNEL32.@)
*/
BOOL
WINAPI
MoveFile
W
(
LPCWSTR
fn1
,
LPCW
STR
fn2
)
BOOL
WINAPI
MoveFile
A
(
LPCSTR
fn1
,
LPC
STR
fn2
)
{
LPSTR
afn1
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
fn1
);
LPSTR
afn2
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
fn2
);
BOOL
res
=
MoveFileA
(
afn1
,
afn2
);
HeapFree
(
GetProcessHeap
(),
0
,
afn1
);
HeapFree
(
GetProcessHeap
(),
0
,
afn2
);
return
res
;
UNICODE_STRING
fn1W
,
fn2W
;
BOOL
ret
;
if
(
!
fn1
||
!
fn2
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
RtlCreateUnicodeStringFromAsciiz
(
&
fn1W
,
fn1
);
RtlCreateUnicodeStringFromAsciiz
(
&
fn2W
,
fn2
);
ret
=
MoveFileW
(
fn1W
.
Buffer
,
fn2W
.
Buffer
);
RtlFreeUnicodeString
(
&
fn1W
);
RtlFreeUnicodeString
(
&
fn2W
);
return
ret
;
}
/**************************************************************************
* CopyFile
A
(KERNEL32.@)
* CopyFile
W
(KERNEL32.@)
*/
BOOL
WINAPI
CopyFile
A
(
LPCSTR
source
,
LPC
STR
dest
,
BOOL
fail_if_exists
)
BOOL
WINAPI
CopyFile
W
(
LPCWSTR
source
,
LPCW
STR
dest
,
BOOL
fail_if_exists
)
{
HANDLE
h1
,
h2
;
BY_HANDLE_FILE_INFORMATION
info
;
DWORD
count
;
BOOL
ret
=
FALSE
;
int
mode
;
char
buffer
[
2048
];
if
((
h1
=
CreateFileA
(
source
,
GENERIC_READ
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
NULL
,
OPEN_EXISTING
,
0
,
0
))
==
INVALID_HANDLE_VALUE
)
if
(
!
source
||
!
dest
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
TRACE
(
"%s -> %s
\n
"
,
debugstr_w
(
source
),
debugstr_w
(
dest
));
if
((
h1
=
CreateFileW
(
source
,
GENERIC_READ
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
NULL
,
OPEN_EXISTING
,
0
,
0
))
==
INVALID_HANDLE_VALUE
)
{
WARN
(
"Unable to open source %s
\n
"
,
debugstr_w
(
source
));
return
FALSE
;
}
if
(
!
GetFileInformationByHandle
(
h1
,
&
info
))
{
WARN
(
"GetFileInformationByHandle returned error for %s
\n
"
,
debugstr_w
(
source
));
CloseHandle
(
h1
);
return
FALSE
;
}
mode
=
(
info
.
dwFileAttributes
&
FILE_ATTRIBUTE_READONLY
)
?
0444
:
0666
;
if
((
h2
=
CreateFile
A
(
dest
,
GENERIC_WRITE
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
NULL
,
if
((
h2
=
CreateFile
W
(
dest
,
GENERIC_WRITE
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
NULL
,
fail_if_exists
?
CREATE_NEW
:
CREATE_ALWAYS
,
info
.
dwFileAttributes
,
h1
))
==
INVALID_HANDLE_VALUE
)
{
WARN
(
"Unable to open dest %s
\n
"
,
debugstr_w
(
dest
));
CloseHandle
(
h1
);
return
FALSE
;
}
while
(
ReadFile
(
h1
,
buffer
,
sizeof
(
buffer
),
&
count
,
NULL
)
&&
count
>
0
)
while
(
ReadFile
(
h1
,
buffer
,
sizeof
(
buffer
),
&
count
,
NULL
)
&&
count
)
{
char
*
p
=
buffer
;
while
(
count
>
0
)
while
(
count
!=
0
)
{
DWORD
res
;
if
(
!
WriteFile
(
h2
,
p
,
count
,
&
res
,
NULL
)
||
!
res
)
goto
done
;
...
...
@@ -2666,69 +2855,71 @@ done:
/**************************************************************************
* CopyFile
W
(KERNEL32.@)
* CopyFile
A
(KERNEL32.@)
*/
BOOL
WINAPI
CopyFile
W
(
LPCWSTR
source
,
LPCW
STR
dest
,
BOOL
fail_if_exists
)
BOOL
WINAPI
CopyFile
A
(
LPCSTR
source
,
LPC
STR
dest
,
BOOL
fail_if_exists
)
{
LPSTR
sourceA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
source
);
LPSTR
destA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
dest
);
BOOL
ret
=
CopyFileA
(
sourceA
,
destA
,
fail_if_exists
);
HeapFree
(
GetProcessHeap
(),
0
,
sourceA
);
HeapFree
(
GetProcessHeap
(),
0
,
destA
);
UNICODE_STRING
sourceW
,
destW
;
BOOL
ret
;
if
(
!
source
||
!
dest
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
RtlCreateUnicodeStringFromAsciiz
(
&
sourceW
,
source
);
RtlCreateUnicodeStringFromAsciiz
(
&
destW
,
dest
);
ret
=
CopyFileW
(
sourceW
.
Buffer
,
destW
.
Buffer
,
fail_if_exists
);
RtlFreeUnicodeString
(
&
sourceW
);
RtlFreeUnicodeString
(
&
destW
);
return
ret
;
}
/**************************************************************************
* CopyFileEx
A
(KERNEL32.@)
* CopyFileEx
W
(KERNEL32.@)
*
* This implementation ignores most of the extra parameters passed-in into
* the "ex" version of the method and calls the CopyFile method.
* It will have to be fixed eventually.
*/
BOOL
WINAPI
CopyFileExA
(
LPCSTR
sourceFilename
,
LPCSTR
destFilename
,
LPPROGRESS_ROUTINE
progressRoutine
,
LPVOID
appData
,
LPBOOL
cancelFlagPointer
,
DWORD
copyFlags
)
{
BOOL
failIfExists
=
FALSE
;
/*
* Interpret the only flag that CopyFile can interpret.
*/
if
(
(
copyFlags
&
COPY_FILE_FAIL_IF_EXISTS
)
!=
0
)
{
failIfExists
=
TRUE
;
}
return
CopyFileA
(
sourceFilename
,
destFilename
,
failIfExists
);
BOOL
WINAPI
CopyFileExW
(
LPCWSTR
sourceFilename
,
LPCWSTR
destFilename
,
LPPROGRESS_ROUTINE
progressRoutine
,
LPVOID
appData
,
LPBOOL
cancelFlagPointer
,
DWORD
copyFlags
)
{
/*
* Interpret the only flag that CopyFile can interpret.
*/
return
CopyFileW
(
sourceFilename
,
destFilename
,
(
copyFlags
&
COPY_FILE_FAIL_IF_EXISTS
)
!=
0
);
}
/**************************************************************************
* CopyFileEx
W
(KERNEL32.@)
* CopyFileEx
A
(KERNEL32.@)
*/
BOOL
WINAPI
CopyFileExW
(
LPCWSTR
sourceFilename
,
LPCWSTR
destFilename
,
LPPROGRESS_ROUTINE
progressRoutine
,
LPVOID
appData
,
LPBOOL
cancelFlagPointer
,
DWORD
copyFlags
)
BOOL
WINAPI
CopyFileExA
(
LPCSTR
sourceFilename
,
LPCSTR
destFilename
,
LPPROGRESS_ROUTINE
progressRoutine
,
LPVOID
appData
,
LPBOOL
cancelFlagPointer
,
DWORD
copyFlags
)
{
LPSTR
sourceA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
sourceFilename
);
LPSTR
destA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
destFilename
);
UNICODE_STRING
sourceW
,
destW
;
BOOL
ret
;
if
(
!
sourceFilename
||
!
destFilename
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
BOOL
ret
=
CopyFileExA
(
sourceA
,
destA
,
progressRoutine
,
appData
,
cancelFlagPointer
,
copyFlags
);
RtlCreateUnicodeStringFromAsciiz
(
&
sourceW
,
sourceFilename
);
RtlCreateUnicodeStringFromAsciiz
(
&
destW
,
destFilename
);
HeapFree
(
GetProcessHeap
(),
0
,
sourceA
);
HeapFree
(
GetProcessHeap
(),
0
,
destA
);
ret
=
CopyFileExW
(
sourceW
.
Buffer
,
destW
.
Buffer
,
progressRoutine
,
appData
,
cancelFlagPointer
,
copyFlags
);
RtlFreeUnicodeString
(
&
sourceW
);
RtlFreeUnicodeString
(
&
destW
);
return
ret
;
}
...
...
@@ -3058,17 +3249,20 @@ BOOL WINAPI UnlockFile(
#endif
/**************************************************************************
*
GetFileAttributesExA [KERNEL32.@]
*
GetFileAttributesExW (KERNEL32.@)
*/
BOOL
WINAPI
GetFileAttributesEx
A
(
LPCSTR
lpFileName
,
GET_FILEEX_INFO_LEVELS
fInfoLevelId
,
BOOL
WINAPI
GetFileAttributesEx
W
(
LPC
W
STR
lpFileName
,
GET_FILEEX_INFO_LEVELS
fInfoLevelId
,
LPVOID
lpFileInformation
)
{
DOS_FULL_NAME
full_name
;
BY_HANDLE_FILE_INFORMATION
info
;
if
(
lpFileName
==
NULL
)
return
FALSE
;
if
(
lpFileInformation
==
NULL
)
return
FALSE
;
if
(
!
lpFileName
||
!
lpFileInformation
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
if
(
fInfoLevelId
==
GetFileExInfoStandard
)
{
LPWIN32_FILE_ATTRIBUTE_DATA
lpFad
=
...
...
@@ -3093,15 +3287,27 @@ BOOL WINAPI GetFileAttributesExA(
/**************************************************************************
*
GetFileAttributesExW [KERNEL32.@]
*
GetFileAttributesExA (KERNEL32.@)
*/
BOOL
WINAPI
GetFileAttributesEx
W
(
LPC
WSTR
lpFileN
ame
,
GET_FILEEX_INFO_LEVELS
fInfoLevelId
,
BOOL
WINAPI
GetFileAttributesEx
A
(
LPC
STR
filen
ame
,
GET_FILEEX_INFO_LEVELS
fInfoLevelId
,
LPVOID
lpFileInformation
)
{
LPSTR
nameA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
lpFileName
);
BOOL
res
=
GetFileAttributesExA
(
nameA
,
fInfoLevelId
,
lpFileInformation
);
HeapFree
(
GetProcessHeap
(),
0
,
nameA
);
return
res
;
UNICODE_STRING
filenameW
;
BOOL
ret
=
FALSE
;
if
(
!
filename
||
!
lpFileInformation
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
if
(
RtlCreateUnicodeStringFromAsciiz
(
&
filenameW
,
filename
))
{
ret
=
GetFileAttributesExW
(
filenameW
.
Buffer
,
fInfoLevelId
,
lpFileInformation
);
RtlFreeUnicodeString
(
&
filenameW
);
}
else
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
ret
;
}
files/profile.c
View file @
d75aed2c
...
...
@@ -40,10 +40,13 @@
#include "winbase.h"
#include "winnls.h"
#include "winerror.h"
#include "ntddk.h"
#include "wine/winbase16.h"
#include "winreg.h"
#include "drive.h"
#include "file.h"
#include "heap.h"
#include "wine/unicode.h"
#include "wine/server.h"
#include "wine/library.h"
#include "wine/debug.h"
...
...
@@ -52,16 +55,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(profile);
typedef
struct
tagPROFILEKEY
{
char
*
value
;
WCHAR
*
value
;
struct
tagPROFILEKEY
*
next
;
char
name
[
1
];
WCHAR
name
[
1
];
}
PROFILEKEY
;
typedef
struct
tagPROFILESECTION
{
struct
tagPROFILEKEY
*
key
;
struct
tagPROFILESECTION
*
next
;
char
name
[
1
];
WCHAR
name
[
1
];
}
PROFILESECTION
;
...
...
@@ -69,9 +72,9 @@ typedef struct
{
BOOL
changed
;
PROFILESECTION
*
section
;
char
*
dos_name
;
WCHAR
*
dos_name
;
char
*
unix_name
;
char
*
filename
;
WCHAR
*
filename
;
time_t
mtime
;
}
PROFILE
;
...
...
@@ -109,23 +112,23 @@ static const char hex[16] = "0123456789ABCDEF";
* Copy the content of an entry into a buffer, removing quotes, and possibly
* translating environment variables.
*/
static
void
PROFILE_CopyEntry
(
char
*
buffer
,
const
char
*
value
,
int
len
,
int
handle_env
)
static
void
PROFILE_CopyEntry
(
LPWSTR
buffer
,
LPCWSTR
value
,
int
len
,
int
handle_env
,
BOOL
strip_quote
)
{
char
quote
=
'\0'
;
const
char
*
p
;
WCHAR
quote
=
'\0'
;
LPCWSTR
p
;
if
(
!
buffer
)
return
;
if
(
(
*
value
==
'\''
)
||
(
*
value
==
'\"'
))
if
(
strip_quote
&&
((
*
value
==
'\''
)
||
(
*
value
==
'\"'
)
))
{
if
(
value
[
1
]
&&
(
value
[
strlen
(
value
)
-
1
]
==
*
value
))
quote
=
*
value
++
;
if
(
value
[
1
]
&&
(
value
[
strlen
W
(
value
)
-
1
]
==
*
value
))
quote
=
*
value
++
;
}
if
(
!
handle_env
)
{
lstrcpyn
A
(
buffer
,
value
,
len
);
if
(
quote
&&
(
len
>=
strlen
(
value
)))
buffer
[
strlen
(
buffer
)
-
1
]
=
'\0'
;
lstrcpyn
W
(
buffer
,
value
,
len
);
if
(
quote
&&
(
len
>=
strlen
W
(
value
)))
buffer
[
strlenW
(
buffer
)
-
1
]
=
'\0'
;
return
;
}
...
...
@@ -133,18 +136,19 @@ static void PROFILE_CopyEntry( char *buffer, const char *value, int len,
{
if
((
*
p
==
'$'
)
&&
(
p
[
1
]
==
'{'
))
{
char
env_val
[
1024
];
const
char
*
env_p
;
const
char
*
p2
=
strchr
(
p
,
'}'
)
;
WCHAR
env_val
[
1024
];
LPCWSTR
p2
=
strchrW
(
p
,
'}'
)
;
int
copy_len
;
if
(
!
p2
)
continue
;
/* ignore it */
lstrcpynA
(
env_val
,
p
+
2
,
min
(
sizeof
(
env_val
),
(
int
)(
p2
-
p
)
-
1
));
if
((
env_p
=
getenv
(
env_val
))
!=
NULL
)
copy_len
=
min
(
1024
,
(
int
)(
p2
-
p
)
-
1
);
strncpyW
(
env_val
,
p
+
2
,
copy_len
);
env_val
[
copy_len
-
1
]
=
0
;
/* ensure 0 termination */
*
buffer
=
0
;
if
(
GetEnvironmentVariableW
(
env_val
,
buffer
,
len
))
{
int
buffer_len
;
lstrcpynA
(
buffer
,
env_p
,
len
);
buffer_len
=
strlen
(
buffer
);
buffer
+=
buffer_len
;
len
-=
buffer_len
;
copy_len
=
strlenW
(
buffer
);
buffer
+=
copy_len
;
len
-=
copy_len
;
}
p
=
p2
+
1
;
}
...
...
@@ -162,14 +166,24 @@ static void PROFILE_CopyEntry( char *buffer, const char *value, int len,
static
void
PROFILE_Save
(
FILE
*
file
,
PROFILESECTION
*
section
)
{
PROFILEKEY
*
key
;
char
buffer
[
PROFILE_MAX_LINE_LEN
];
for
(
;
section
;
section
=
section
->
next
)
{
if
(
section
->
name
[
0
])
fprintf
(
file
,
"
\r\n
[%s]
\r\n
"
,
section
->
name
);
if
(
section
->
name
[
0
])
{
WideCharToMultiByte
(
CP_ACP
,
0
,
section
->
name
,
-
1
,
buffer
,
sizeof
(
buffer
),
NULL
,
NULL
);
fprintf
(
file
,
"
\r\n
[%s]
\r\n
"
,
buffer
);
}
for
(
key
=
section
->
key
;
key
;
key
=
key
->
next
)
{
fprintf
(
file
,
"%s"
,
key
->
name
);
if
(
key
->
value
)
fprintf
(
file
,
"=%s"
,
key
->
value
);
WideCharToMultiByte
(
CP_ACP
,
0
,
key
->
name
,
-
1
,
buffer
,
sizeof
(
buffer
),
NULL
,
NULL
);
fprintf
(
file
,
"%s"
,
buffer
);
if
(
key
->
value
)
{
WideCharToMultiByte
(
CP_ACP
,
0
,
key
->
value
,
-
1
,
buffer
,
sizeof
(
buffer
),
NULL
,
NULL
);
fprintf
(
file
,
"=%s"
,
buffer
);
}
fprintf
(
file
,
"
\r\n
"
);
}
}
...
...
@@ -217,7 +231,7 @@ static PROFILESECTION *PROFILE_Load( FILE *file )
{
char
buffer
[
PROFILE_MAX_LINE_LEN
];
char
*
p
,
*
p2
;
int
line
=
0
;
int
line
=
0
,
len
;
PROFILESECTION
*
section
,
*
first_section
;
PROFILESECTION
**
next_section
;
PROFILEKEY
*
key
,
*
prev_key
,
**
next_key
;
...
...
@@ -247,9 +261,10 @@ static PROFILESECTION *PROFILE_Load( FILE *file )
{
*
p2
=
'\0'
;
p
++
;
if
(
!
(
section
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
section
)
+
strlen
(
p
)
)))
len
=
strlen
(
p
);
if
(
!
(
section
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
section
)
+
len
*
sizeof
(
WCHAR
)
)))
break
;
strcpy
(
section
->
name
,
p
);
MultiByteToWideChar
(
CP_ACP
,
0
,
p
,
-
1
,
section
->
name
,
len
+
1
);
section
->
key
=
NULL
;
section
->
next
=
NULL
;
*
next_section
=
section
;
...
...
@@ -257,7 +272,7 @@ static PROFILESECTION *PROFILE_Load( FILE *file )
next_key
=
&
section
->
key
;
prev_key
=
NULL
;
TRACE
(
"New section:
'%s'
\n
"
,
section
->
name
);
TRACE
(
"New section:
%s
\n
"
,
debugstr_w
(
section
->
name
)
);
continue
;
}
...
...
@@ -276,12 +291,14 @@ static PROFILESECTION *PROFILE_Load( FILE *file )
if
(
*
p
||
!
prev_key
||
*
prev_key
->
name
)
{
if
(
!
(
key
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
key
)
+
strlen
(
p
)
)))
break
;
strcpy
(
key
->
name
,
p
);
len
=
strlen
(
p
);
if
(
!
(
key
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
key
)
+
len
*
sizeof
(
WCHAR
)
)))
break
;
MultiByteToWideChar
(
CP_ACP
,
0
,
p
,
-
1
,
key
->
name
,
len
+
1
);
if
(
p2
)
{
key
->
value
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlen
(
p2
)
+
1
);
strcpy
(
key
->
value
,
p2
);
len
=
strlen
(
p2
)
+
1
;
key
->
value
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
*
sizeof
(
WCHAR
)
);
MultiByteToWideChar
(
CP_ACP
,
0
,
p2
,
-
1
,
key
->
value
,
len
);
}
else
key
->
value
=
NULL
;
...
...
@@ -290,7 +307,8 @@ static PROFILESECTION *PROFILE_Load( FILE *file )
next_key
=
&
key
->
next
;
prev_key
=
key
;
TRACE
(
"New key: name='%s', value='%s'
\n
"
,
key
->
name
,
key
->
value
?
key
->
value
:
"(none)"
);
TRACE
(
"New key: name=%s, value=%s
\n
"
,
debugstr_w
(
key
->
name
),
key
->
value
?
debugstr_w
(
key
->
value
)
:
"(none)"
);
}
}
return
first_section
;
...
...
@@ -380,11 +398,11 @@ static void convert_config( FILE *in, const char *output_name )
*
* Delete a section from a profile tree.
*/
static
BOOL
PROFILE_DeleteSection
(
PROFILESECTION
**
section
,
LPCSTR
name
)
static
BOOL
PROFILE_DeleteSection
(
PROFILESECTION
**
section
,
LPC
W
STR
name
)
{
while
(
*
section
)
{
if
((
*
section
)
->
name
[
0
]
&&
!
strc
asecmp
(
(
*
section
)
->
name
,
name
))
if
((
*
section
)
->
name
[
0
]
&&
!
strc
mpiW
(
(
*
section
)
->
name
,
name
))
{
PROFILESECTION
*
to_del
=
*
section
;
*
section
=
to_del
->
next
;
...
...
@@ -404,16 +422,16 @@ static BOOL PROFILE_DeleteSection( PROFILESECTION **section, LPCSTR name )
* Delete a key from a profile tree.
*/
static
BOOL
PROFILE_DeleteKey
(
PROFILESECTION
**
section
,
LPC
STR
section_name
,
LPC
STR
key_name
)
LPC
WSTR
section_name
,
LPCW
STR
key_name
)
{
while
(
*
section
)
{
if
((
*
section
)
->
name
[
0
]
&&
!
strc
asecmp
(
(
*
section
)
->
name
,
section_name
))
if
((
*
section
)
->
name
[
0
]
&&
!
strc
mpiW
(
(
*
section
)
->
name
,
section_name
))
{
PROFILEKEY
**
key
=
&
(
*
section
)
->
key
;
while
(
*
key
)
{
if
(
!
strc
asecmp
(
(
*
key
)
->
name
,
key_name
))
if
(
!
strc
mpiW
(
(
*
key
)
->
name
,
key_name
))
{
PROFILEKEY
*
to_del
=
*
key
;
*
key
=
to_del
->
next
;
...
...
@@ -435,12 +453,12 @@ static BOOL PROFILE_DeleteKey( PROFILESECTION **section,
*
* Delete all keys from a profile tree.
*/
void
PROFILE_DeleteAllKeys
(
LPCSTR
section_name
)
void
PROFILE_DeleteAllKeys
(
LPC
W
STR
section_name
)
{
PROFILESECTION
**
section
=
&
CurProfile
->
section
;
while
(
*
section
)
{
if
((
*
section
)
->
name
[
0
]
&&
!
strc
asecmp
(
(
*
section
)
->
name
,
section_name
))
if
((
*
section
)
->
name
[
0
]
&&
!
strc
mpiW
(
(
*
section
)
->
name
,
section_name
))
{
PROFILEKEY
**
key
=
&
(
*
section
)
->
key
;
while
(
*
key
)
...
...
@@ -462,26 +480,26 @@ void PROFILE_DeleteAllKeys( LPCSTR section_name)
*
* Find a key in a profile tree, optionally creating it.
*/
static
PROFILEKEY
*
PROFILE_Find
(
PROFILESECTION
**
section
,
const
char
*
section_name
,
const
char
*
key_name
,
BOOL
create
,
BOOL
create_always
)
static
PROFILEKEY
*
PROFILE_Find
(
PROFILESECTION
**
section
,
LPCWSTR
section_name
,
LPCWSTR
key_name
,
BOOL
create
,
BOOL
create_always
)
{
const
char
*
p
;
LPCWSTR
p
;
int
seclen
,
keylen
;
while
(
PROFILE_isspace
(
*
section_name
))
section_name
++
;
p
=
section_name
+
strlen
(
section_name
)
-
1
;
p
=
section_name
+
strlen
W
(
section_name
)
-
1
;
while
((
p
>
section_name
)
&&
PROFILE_isspace
(
*
p
))
p
--
;
seclen
=
p
-
section_name
+
1
;
while
(
PROFILE_isspace
(
*
key_name
))
key_name
++
;
p
=
key_name
+
strlen
(
key_name
)
-
1
;
p
=
key_name
+
strlen
W
(
key_name
)
-
1
;
while
((
p
>
key_name
)
&&
PROFILE_isspace
(
*
p
))
p
--
;
keylen
=
p
-
key_name
+
1
;
while
(
*
section
)
{
if
(
((
*
section
)
->
name
[
0
])
&&
(
!
(
strnc
asecmp
(
(
*
section
)
->
name
,
section_name
,
seclen
)))
&&
(
!
(
strnc
mpiW
(
(
*
section
)
->
name
,
section_name
,
seclen
)))
&&
(((
*
section
)
->
name
)[
seclen
]
==
'\0'
)
)
{
PROFILEKEY
**
key
=
&
(
*
section
)
->
key
;
...
...
@@ -494,16 +512,16 @@ static PROFILEKEY *PROFILE_Find( PROFILESECTION **section, const char *section_n
*/
if
(
!
create_always
)
{
if
(
(
!
(
strnc
asecmp
(
(
*
key
)
->
name
,
key_name
,
keylen
)))
if
(
(
!
(
strnc
mpiW
(
(
*
key
)
->
name
,
key_name
,
keylen
)))
&&
(((
*
key
)
->
name
)[
keylen
]
==
'\0'
)
)
return
*
key
;
}
key
=
&
(
*
key
)
->
next
;
}
if
(
!
create
)
return
NULL
;
if
(
!
(
*
key
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
PROFILEKEY
)
+
strlen
(
key_name
)
)))
if
(
!
(
*
key
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
PROFILEKEY
)
+
strlen
W
(
key_name
)
*
sizeof
(
WCHAR
)
)))
return
NULL
;
strcpy
(
(
*
key
)
->
name
,
key_name
);
strcpy
W
(
(
*
key
)
->
name
,
key_name
);
(
*
key
)
->
value
=
NULL
;
(
*
key
)
->
next
=
NULL
;
return
*
key
;
...
...
@@ -511,17 +529,17 @@ static PROFILEKEY *PROFILE_Find( PROFILESECTION **section, const char *section_n
section
=
&
(
*
section
)
->
next
;
}
if
(
!
create
)
return
NULL
;
*
section
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
PROFILESECTION
)
+
strlen
(
section_name
)
);
*
section
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
PROFILESECTION
)
+
strlen
W
(
section_name
)
*
sizeof
(
WCHAR
)
);
if
(
*
section
==
NULL
)
return
NULL
;
strcpy
(
(
*
section
)
->
name
,
section_name
);
strcpy
W
(
(
*
section
)
->
name
,
section_name
);
(
*
section
)
->
next
=
NULL
;
if
(
!
((
*
section
)
->
key
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
PROFILEKEY
)
+
strlen
(
key_name
)
)))
sizeof
(
PROFILEKEY
)
+
strlen
W
(
key_name
)
*
sizeof
(
WCHAR
)
)))
{
HeapFree
(
GetProcessHeap
(),
0
,
*
section
);
return
NULL
;
}
strcpy
(
(
*
section
)
->
key
->
name
,
key_name
);
strcpy
W
(
(
*
section
)
->
key
->
name
,
key_name
);
(
*
section
)
->
key
->
value
=
NULL
;
(
*
section
)
->
key
->
next
=
NULL
;
return
(
*
section
)
->
key
;
...
...
@@ -549,24 +567,28 @@ static BOOL PROFILE_FlushFile(void)
if
(
!
CurProfile
->
changed
||
!
CurProfile
->
dos_name
)
return
TRUE
;
if
(
!
(
unix_name
=
CurProfile
->
unix_name
)
||
!
(
file
=
fopen
(
unix_name
,
"w"
)))
{
int
drive
=
toupperW
(
CurProfile
->
dos_name
[
0
])
-
'A'
;
WCHAR
*
name
;
/* Try to create it in $HOME/.wine */
/* FIXME: this will need a more general solution */
strcpy
(
buffer
,
wine_get_config_dir
()
);
p
=
buffer
+
strlen
(
buffer
);
*
p
++
=
'/'
;
strcpy
(
p
,
strrchr
(
CurProfile
->
dos_name
,
'\\'
)
+
1
);
_strlwr
(
p
);
*
p
=
0
;
/* make strlen() below happy */
name
=
strrchrW
(
CurProfile
->
dos_name
,
'\\'
)
+
1
;
WideCharToMultiByte
(
DRIVE_GetCodepage
(
drive
),
0
,
name
,
-
1
,
p
,
sizeof
(
buffer
)
-
strlen
(
buffer
),
NULL
,
NULL
);
file
=
fopen
(
buffer
,
"w"
);
unix_name
=
buffer
;
}
if
(
!
file
)
{
WARN
(
"could not save profile file %s
\n
"
,
CurProfile
->
dos_name
);
WARN
(
"could not save profile file %s
\n
"
,
debugstr_w
(
CurProfile
->
dos_name
)
);
return
FALSE
;
}
TRACE
(
"Saving
'%s' into '%s'
\n
"
,
CurProfile
->
dos_name
,
unix_name
);
TRACE
(
"Saving
%s into '%s'
\n
"
,
debugstr_w
(
CurProfile
->
dos_name
)
,
unix_name
);
PROFILE_Save
(
file
,
CurProfile
->
section
);
fclose
(
file
);
CurProfile
->
changed
=
FALSE
;
...
...
@@ -602,11 +624,13 @@ static void PROFILE_ReleaseFile(void)
*
* Open a profile file, checking the cached file first.
*/
static
BOOL
PROFILE_Open
(
LPCSTR
filename
)
static
BOOL
PROFILE_Open
(
LPC
W
STR
filename
)
{
DOS_FULL_NAME
full_name
;
char
buffer
[
MAX_PATHNAME_LEN
];
char
*
newdos_name
,
*
p
;
WCHAR
*
newdos_name
;
WCHAR
*
name
;
char
*
p
;
FILE
*
file
=
NULL
;
int
i
,
j
;
struct
stat
buf
;
...
...
@@ -629,23 +653,26 @@ static BOOL PROFILE_Open( LPCSTR filename )
/* Check for a match */
if
(
strchr
(
filename
,
'/'
)
||
strchr
(
filename
,
'\\'
)
||
strchr
(
filename
,
':'
))
if
(
strchr
W
(
filename
,
'/'
)
||
strchrW
(
filename
,
'\\'
)
||
strchr
W
(
filename
,
':'
))
{
if
(
!
DOSFS_GetFullName
(
filename
,
FALSE
,
&
full_name
))
return
FALSE
;
}
else
{
GetWindowsDirectoryA
(
buffer
,
sizeof
(
buffer
)
);
strcat
(
buffer
,
"
\\
"
);
strcat
(
buffer
,
filename
);
if
(
!
DOSFS_GetFullName
(
buffer
,
FALSE
,
&
full_name
))
return
FALSE
;
static
const
WCHAR
bkslashW
[]
=
{
'\\'
,
0
};
WCHAR
windirW
[
MAX_PATH
];
GetWindowsDirectoryW
(
windirW
,
MAX_PATH
);
strcatW
(
windirW
,
bkslashW
);
strcatW
(
windirW
,
filename
);
if
(
!
DOSFS_GetFullName
(
windirW
,
FALSE
,
&
full_name
))
return
FALSE
;
}
for
(
i
=
0
;
i
<
N_CACHED_PROFILES
;
i
++
)
{
if
((
MRUProfile
[
i
]
->
filename
&&
!
strcmp
(
filename
,
MRUProfile
[
i
]
->
filename
))
||
(
MRUProfile
[
i
]
->
dos_name
&&
!
strcmp
(
full_name
.
short_name
,
MRUProfile
[
i
]
->
dos_name
)))
if
((
MRUProfile
[
i
]
->
filename
&&
!
strcmp
W
(
filename
,
MRUProfile
[
i
]
->
filename
))
||
(
MRUProfile
[
i
]
->
dos_name
&&
!
strcmp
W
(
full_name
.
short_name
,
MRUProfile
[
i
]
->
dos_name
)))
{
if
(
i
)
{
...
...
@@ -657,10 +684,10 @@ static BOOL PROFILE_Open( LPCSTR filename )
}
if
(
!
stat
(
CurProfile
->
unix_name
,
&
buf
)
&&
CurProfile
->
mtime
==
buf
.
st_mtime
)
TRACE
(
"(%s): already opened (mru=%d)
\n
"
,
filename
,
i
);
debugstr_w
(
filename
)
,
i
);
else
TRACE
(
"(%s): already opened, needs refreshing (mru=%d)
\n
"
,
filename
,
i
);
debugstr_w
(
filename
)
,
i
);
return
TRUE
;
}
}
...
...
@@ -679,11 +706,11 @@ static BOOL PROFILE_Open( LPCSTR filename )
if
(
CurProfile
->
filename
)
PROFILE_ReleaseFile
();
/* OK, now that CurProfile is definitely free we assign it our new file */
newdos_name
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlen
(
full_name
.
short_name
)
+
1
);
strcpy
(
newdos_name
,
full_name
.
short_name
);
newdos_name
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
strlenW
(
full_name
.
short_name
)
+
1
)
*
sizeof
(
WCHAR
)
);
strcpy
W
(
newdos_name
,
full_name
.
short_name
);
CurProfile
->
dos_name
=
newdos_name
;
CurProfile
->
filename
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlen
(
filename
)
+
1
);
strcpy
(
CurProfile
->
filename
,
filename
);
CurProfile
->
filename
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
strlenW
(
filename
)
+
1
)
*
sizeof
(
WCHAR
)
);
strcpy
W
(
CurProfile
->
filename
,
filename
);
/* Try to open the profile file, first in $HOME/.wine */
...
...
@@ -691,23 +718,23 @@ static BOOL PROFILE_Open( LPCSTR filename )
strcpy
(
buffer
,
wine_get_config_dir
()
);
p
=
buffer
+
strlen
(
buffer
);
*
p
++
=
'/'
;
strcpy
(
p
,
strrchr
(
newdos_name
,
'\\'
)
+
1
);
_strlwr
(
p
);
*
p
=
0
;
/* make strlen() below happy */
name
=
strrchrW
(
newdos_name
,
'\\'
)
+
1
;
WideCharToMultiByte
(
DRIVE_GetCodepage
(
full_name
.
drive
),
0
,
name
,
-
1
,
p
,
sizeof
(
buffer
)
-
strlen
(
buffer
),
NULL
,
NULL
);
if
((
file
=
fopen
(
buffer
,
"r"
)))
{
TRACE
(
"(%s): found it in %s
\n
"
,
filename
,
buffer
);
TRACE
(
"(%s): found it in %s
\n
"
,
debugstr_w
(
filename
),
buffer
);
CurProfile
->
unix_name
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlen
(
buffer
)
+
1
);
strcpy
(
CurProfile
->
unix_name
,
buffer
);
}
if
(
!
file
)
else
{
CurProfile
->
unix_name
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlen
(
full_name
.
long_name
)
+
1
);
strcpy
(
CurProfile
->
unix_name
,
full_name
.
long_name
);
if
((
file
=
fopen
(
full_name
.
long_name
,
"r"
)))
TRACE
(
"(%s): found it in %s
\n
"
,
filename
,
full_name
.
long_name
);
debugstr_w
(
filename
)
,
full_name
.
long_name
);
}
if
(
file
)
...
...
@@ -720,7 +747,7 @@ static BOOL PROFILE_Open( LPCSTR filename )
else
{
/* Does not exist yet, we will create it in PROFILE_FlushFile */
WARN
(
"profile file %s not found
\n
"
,
newdos_name
);
WARN
(
"profile file %s not found
\n
"
,
debugstr_w
(
newdos_name
)
);
}
return
TRUE
;
}
...
...
@@ -732,17 +759,19 @@ static BOOL PROFILE_Open( LPCSTR filename )
* Returns all keys of a section.
* If return_values is TRUE, also include the corresponding values.
*/
static
INT
PROFILE_GetSection
(
PROFILESECTION
*
section
,
LPCSTR
section_name
,
LPSTR
buffer
,
UINT
len
,
BOOL
handle_env
,
static
INT
PROFILE_GetSection
(
PROFILESECTION
*
section
,
LPC
W
STR
section_name
,
LP
W
STR
buffer
,
UINT
len
,
BOOL
handle_env
,
BOOL
return_values
)
{
PROFILEKEY
*
key
;
if
(
!
buffer
)
return
0
;
TRACE
(
"%s,%p,%u
\n
"
,
debugstr_w
(
section_name
),
buffer
,
len
);
while
(
section
)
{
if
(
section
->
name
[
0
]
&&
!
strc
asecmp
(
section
->
name
,
section_name
))
if
(
section
->
name
[
0
]
&&
!
strc
mpiW
(
section
->
name
,
section_name
))
{
UINT
oldlen
=
len
;
for
(
key
=
section
->
key
;
key
;
key
=
key
->
next
)
...
...
@@ -750,17 +779,17 @@ static INT PROFILE_GetSection( PROFILESECTION *section, LPCSTR section_name,
if
(
len
<=
2
)
break
;
if
(
!*
key
->
name
)
continue
;
/* Skip empty lines */
if
(
IS_ENTRY_COMMENT
(
key
->
name
))
continue
;
/* Skip comments */
PROFILE_CopyEntry
(
buffer
,
key
->
name
,
len
-
1
,
handle_env
);
len
-=
strlen
(
buffer
)
+
1
;
buffer
+=
strlen
(
buffer
)
+
1
;
PROFILE_CopyEntry
(
buffer
,
key
->
name
,
len
-
1
,
handle_env
,
0
);
len
-=
strlen
W
(
buffer
)
+
1
;
buffer
+=
strlen
W
(
buffer
)
+
1
;
if
(
len
<
2
)
break
;
if
(
return_values
&&
key
->
value
)
{
buffer
[
-
1
]
=
'='
;
PROFILE_CopyEntry
(
buffer
,
key
->
value
,
len
-
1
,
handle_env
);
len
-=
strlen
(
buffer
)
+
1
;
buffer
+=
strlen
(
buffer
)
+
1
;
key
->
value
,
len
-
1
,
handle_env
,
0
);
len
-=
strlen
W
(
buffer
)
+
1
;
buffer
+=
strlen
W
(
buffer
)
+
1
;
}
}
*
buffer
=
'\0'
;
...
...
@@ -783,9 +812,9 @@ static INT PROFILE_GetSection( PROFILESECTION *section, LPCSTR section_name,
}
/* See GetPrivateProfileSectionNamesA for documentation */
static
INT
PROFILE_GetSectionNames
(
LPSTR
buffer
,
UINT
len
)
static
INT
PROFILE_GetSectionNames
(
LP
W
STR
buffer
,
UINT
len
)
{
LPSTR
buf
;
LP
W
STR
buf
;
UINT
f
,
l
;
PROFILESECTION
*
section
;
...
...
@@ -801,17 +830,17 @@ static INT PROFILE_GetSectionNames( LPSTR buffer, UINT len )
section
=
CurProfile
->
section
;
while
((
section
!=
NULL
))
{
if
(
section
->
name
[
0
])
{
l
=
strlen
(
section
->
name
)
+
1
;
l
=
strlen
W
(
section
->
name
)
+
1
;
if
(
l
>
f
)
{
if
(
f
>
0
)
{
strncpy
(
buf
,
section
->
name
,
f
-
1
);
strncpy
W
(
buf
,
section
->
name
,
f
-
1
);
buf
+=
f
-
1
;
*
buf
++=
'\0'
;
}
*
buf
=
'\0'
;
return
len
-
2
;
}
strcpy
(
buf
,
section
->
name
);
strcpy
W
(
buf
,
section
->
name
);
buf
+=
l
;
f
-=
l
;
}
...
...
@@ -844,25 +873,29 @@ static INT PROFILE_GetSectionNames( LPSTR buffer, UINT len )
*
*
*/
static
INT
PROFILE_GetString
(
LPC
STR
section
,
LPC
STR
key_name
,
LPCSTR
def_val
,
LP
STR
buffer
,
UINT
len
)
static
INT
PROFILE_GetString
(
LPC
WSTR
section
,
LPCW
STR
key_name
,
LPCWSTR
def_val
,
LPW
STR
buffer
,
UINT
len
)
{
PROFILEKEY
*
key
=
NULL
;
static
const
WCHAR
empty_strW
[]
=
{
0
};
if
(
!
buffer
)
return
0
;
if
(
!
def_val
)
def_val
=
""
;
if
(
!
def_val
)
def_val
=
empty_strW
;
if
(
key_name
)
{
if
(
!
key_name
[
0
])
{
/* Win95 returns 0 on keyname "". Tested with Likse32 bon 000227 */
return
0
;
}
key
=
PROFILE_Find
(
&
CurProfile
->
section
,
section
,
key_name
,
FALSE
,
FALSE
);
PROFILE_CopyEntry
(
buffer
,
(
key
&&
key
->
value
)
?
key
->
value
:
def_val
,
len
,
FALSE
);
TRACE
(
"('%s','%s','%s'): returning '%s'
\n
"
,
section
,
key_name
,
def_val
,
buffer
);
return
strlen
(
buffer
);
len
,
FALSE
,
TRUE
);
TRACE
(
"(%s,%s,%s): returning %s
\n
"
,
debugstr_w
(
section
),
debugstr_w
(
key_name
),
debugstr_w
(
def_val
),
debugstr_w
(
buffer
)
);
return
strlenW
(
buffer
);
}
/* no "else" here ! */
if
(
section
&&
section
[
0
])
...
...
@@ -870,8 +903,8 @@ static INT PROFILE_GetString( LPCSTR section, LPCSTR key_name,
INT
ret
=
PROFILE_GetSection
(
CurProfile
->
section
,
section
,
buffer
,
len
,
FALSE
,
FALSE
);
if
(
!
buffer
[
0
])
/* no luck -> def_val */
{
PROFILE_CopyEntry
(
buffer
,
def_val
,
len
,
FALSE
);
ret
=
strlen
(
buffer
);
PROFILE_CopyEntry
(
buffer
,
def_val
,
len
,
FALSE
,
TRUE
);
ret
=
strlen
W
(
buffer
);
}
return
ret
;
}
...
...
@@ -885,12 +918,12 @@ static INT PROFILE_GetString( LPCSTR section, LPCSTR key_name,
*
* Set a profile string.
*/
static
BOOL
PROFILE_SetString
(
LPC
STR
section_name
,
LPC
STR
key_name
,
LPCSTR
value
,
BOOL
create_always
)
static
BOOL
PROFILE_SetString
(
LPC
WSTR
section_name
,
LPCW
STR
key_name
,
LPC
W
STR
value
,
BOOL
create_always
)
{
if
(
!
key_name
)
/* Delete a whole section */
{
TRACE
(
"(
'%s')
\n
"
,
section_name
);
TRACE
(
"(
%s)
\n
"
,
debugstr_w
(
section_name
)
);
CurProfile
->
changed
|=
PROFILE_DeleteSection
(
&
CurProfile
->
section
,
section_name
);
return
TRUE
;
/* Even if PROFILE_DeleteSection() has failed,
...
...
@@ -898,8 +931,7 @@ static BOOL PROFILE_SetString( LPCSTR section_name, LPCSTR key_name,
}
else
if
(
!
value
)
/* Delete a key */
{
TRACE
(
"('%s','%s')
\n
"
,
section_name
,
key_name
);
TRACE
(
"(%s,%s)
\n
"
,
debugstr_w
(
section_name
),
debugstr_w
(
key_name
)
);
CurProfile
->
changed
|=
PROFILE_DeleteKey
(
&
CurProfile
->
section
,
section_name
,
key_name
);
return
TRUE
;
/* same error handling as above */
...
...
@@ -908,8 +940,8 @@ static BOOL PROFILE_SetString( LPCSTR section_name, LPCSTR key_name,
{
PROFILEKEY
*
key
=
PROFILE_Find
(
&
CurProfile
->
section
,
section_name
,
key_name
,
TRUE
,
create_always
);
TRACE
(
"(
'%s','%s','%s'):
\n
"
,
section_name
,
key_name
,
value
);
TRACE
(
"(
%s,%s,%s):
\n
"
,
debugstr_w
(
section_name
),
debugstr_w
(
key_name
),
debugstr_w
(
value
)
);
if
(
!
key
)
return
FALSE
;
if
(
key
->
value
)
{
...
...
@@ -917,17 +949,17 @@ static BOOL PROFILE_SetString( LPCSTR section_name, LPCSTR key_name,
* friends too, they should not happen here anyway. */
while
(
PROFILE_isspace
(
*
value
))
value
++
;
if
(
!
strcmp
(
key
->
value
,
value
))
if
(
!
strcmp
W
(
key
->
value
,
value
))
{
TRACE
(
" no change needed
\n
"
);
return
TRUE
;
/* No change needed */
}
TRACE
(
" replacing
'%s'
\n
"
,
key
->
value
);
TRACE
(
" replacing
%s
\n
"
,
debugstr_w
(
key
->
value
)
);
HeapFree
(
GetProcessHeap
(),
0
,
key
->
value
);
}
else
TRACE
(
" creating key
\n
"
);
key
->
value
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlen
(
value
)
+
1
);
strcpy
(
key
->
value
,
value
);
key
->
value
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
strlenW
(
value
)
+
1
)
*
sizeof
(
WCHAR
)
);
strcpy
W
(
key
->
value
,
value
);
CurProfile
->
changed
=
TRUE
;
}
return
TRUE
;
...
...
@@ -939,32 +971,31 @@ static BOOL PROFILE_SetString( LPCSTR section_name, LPCSTR key_name,
*
* Get a config string from the wine.ini file.
*/
int
PROFILE_GetWineIniString
(
const
char
*
section
,
const
char
*
key_name
,
const
char
*
def
,
char
*
buffer
,
int
len
)
int
PROFILE_GetWineIniString
(
LPCWSTR
section
,
LPCWSTR
key_name
,
LPCWSTR
def
,
LPWSTR
buffer
,
int
len
)
{
char
tmp
[
PROFILE_MAX_LINE_LEN
];
WCHAR
tmp
[
PROFILE_MAX_LINE_LEN
];
HKEY
hkey
;
DWORD
err
;
if
(
!
(
err
=
RegOpenKey
A
(
wine_profile_key
,
section
,
&
hkey
)))
if
(
!
(
err
=
RegOpenKey
W
(
wine_profile_key
,
section
,
&
hkey
)))
{
DWORD
type
;
DWORD
count
=
sizeof
(
tmp
);
err
=
RegQueryValueEx
A
(
hkey
,
key_name
,
0
,
&
type
,
tmp
,
&
count
);
err
=
RegQueryValueEx
W
(
hkey
,
key_name
,
0
,
&
type
,
(
LPBYTE
)
tmp
,
&
count
);
RegCloseKey
(
hkey
);
}
PROFILE_CopyEntry
(
buffer
,
err
?
def
:
tmp
,
len
,
TRUE
);
TRACE
(
"('%s','%s','%s'): returning '%s'
\n
"
,
section
,
key_name
,
def
,
buffer
);
return
strlen
(
buffer
);
PROFILE_CopyEntry
(
buffer
,
err
?
def
:
tmp
,
len
,
TRUE
,
TRUE
);
TRACE
(
"(%s,%s,%s): returning %s
\n
"
,
debugstr_w
(
section
),
debugstr_w
(
key_name
),
debugstr_w
(
def
),
debugstr_w
(
buffer
)
);
return
strlenW
(
buffer
);
}
/******************************************************************************
*
* int PROFILE_GetWineIniBool(
* char const *section,
* char const *key_name,
* int def )
* PROFILE_GetWineIniBool
*
* Reads a boolean value from the wine.ini file. This function attempts to
* be user-friendly by accepting 'n', 'N' (no), 'f', 'F' (false), or '0'
...
...
@@ -975,15 +1006,13 @@ int PROFILE_GetWineIniString( const char *section, const char *key_name,
* for existence by setting def to something other than 0 or 1 and
* examining the return value.
*/
int
PROFILE_GetWineIniBool
(
char
const
*
section
,
char
const
*
key_name
,
int
def
)
int
PROFILE_GetWineIniBool
(
LPCWSTR
section
,
LPCWSTR
key_name
,
int
def
)
{
char
key_value
[
2
];
static
const
WCHAR
def_valueW
[]
=
{
'~'
,
0
};
WCHAR
key_value
[
2
];
int
retval
;
PROFILE_GetWineIniString
(
section
,
key_name
,
"~"
,
key_value
,
2
);
PROFILE_GetWineIniString
(
section
,
key_name
,
def_valueW
,
key_value
,
2
);
switch
(
key_value
[
0
])
{
case
'n'
:
...
...
@@ -1006,7 +1035,7 @@ int PROFILE_GetWineIniBool(
retval
=
def
;
}
TRACE
(
"(
\"
%s
\"
,
\"
%s
\"
, %s), [%c], ret %s.
\n
"
,
section
,
key_name
,
TRACE
(
"(
%s, %s, %s), [%c], ret %s
\n
"
,
debugstr_w
(
section
),
debugstr_w
(
key_name
)
,
def
?
"TRUE"
:
"FALSE"
,
key_value
[
0
],
retval
?
"TRUE"
:
"FALSE"
);
...
...
@@ -1133,21 +1162,24 @@ UINT WINAPI GetProfileIntW( LPCWSTR section, LPCWSTR entry, INT def_val )
* - of Keys in a Section if 'entry' is NULL
* (see MSDN doc for GetPrivateProfileString)
*/
static
int
PROFILE_GetPrivateProfileString
(
LPC
STR
section
,
LPC
STR
entry
,
LPC
STR
def_val
,
LP
STR
buffer
,
UINT
16
len
,
LPC
STR
filename
,
static
int
PROFILE_GetPrivateProfileString
(
LPC
WSTR
section
,
LPCW
STR
entry
,
LPC
WSTR
def_val
,
LPW
STR
buffer
,
UINT
len
,
LPCW
STR
filename
,
BOOL
allow_section_name_copy
)
{
int
ret
;
LPSTR
pDefVal
=
NULL
;
LP
W
STR
pDefVal
=
NULL
;
if
(
!
filename
)
filename
=
"win.ini"
;
filename
=
wininiW
;
TRACE
(
"%s,%s,%s,%p,%u,%s
\n
"
,
debugstr_w
(
section
),
debugstr_w
(
entry
),
debugstr_w
(
def_val
),
buffer
,
len
,
debugstr_w
(
filename
));
/* strip any trailing ' ' of def_val. */
if
(
def_val
)
{
LP
STR
p
=
(
LPSTR
)
&
def_val
[
strlen
(
def_val
)];
/* even "" works ! */
LP
CWSTR
p
=
&
def_val
[
strlenW
(
def_val
)];
/* even "" works ! */
while
(
p
>
def_val
)
{
...
...
@@ -1157,14 +1189,14 @@ static int PROFILE_GetPrivateProfileString( LPCSTR section, LPCSTR entry,
}
if
(
*
p
==
' '
)
/* ouch, contained trailing ' ' */
{
int
len
=
(
int
)
p
-
(
int
)
def_val
;
pDefVal
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
+
1
);
strncpy
(
pDefVal
,
def_val
,
len
);
int
len
=
(
int
)
(
p
-
def_val
)
;
pDefVal
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
len
+
1
)
*
sizeof
(
WCHAR
)
);
strncpy
W
(
pDefVal
,
def_val
,
len
);
pDefVal
[
len
]
=
'\0'
;
}
}
if
(
!
pDefVal
)
pDefVal
=
(
LPSTR
)
def_val
;
pDefVal
=
(
LP
W
STR
)
def_val
;
EnterCriticalSection
(
&
PROFILE_CritSect
);
...
...
@@ -1175,8 +1207,8 @@ static int PROFILE_GetPrivateProfileString( LPCSTR section, LPCSTR entry,
/* PROFILE_GetString already handles the 'entry == NULL' case */
ret
=
PROFILE_GetString
(
section
,
entry
,
pDefVal
,
buffer
,
len
);
}
else
{
lstrcpyn
A
(
buffer
,
pDefVal
,
len
);
ret
=
strlen
(
buffer
);
lstrcpyn
W
(
buffer
,
pDefVal
,
len
);
ret
=
strlen
W
(
buffer
);
}
LeaveCriticalSection
(
&
PROFILE_CritSect
);
...
...
@@ -1184,6 +1216,8 @@ static int PROFILE_GetPrivateProfileString( LPCSTR section, LPCSTR entry,
if
(
pDefVal
!=
def_val
)
/* allocated */
HeapFree
(
GetProcessHeap
(),
0
,
pDefVal
);
TRACE
(
"returning %s, %d
\n
"
,
debugstr_w
(
buffer
),
ret
);
return
ret
;
}
...
...
@@ -1194,8 +1228,41 @@ INT16 WINAPI GetPrivateProfileString16( LPCSTR section, LPCSTR entry,
LPCSTR
def_val
,
LPSTR
buffer
,
UINT16
len
,
LPCSTR
filename
)
{
return
PROFILE_GetPrivateProfileString
(
section
,
entry
,
def_val
,
buffer
,
len
,
filename
,
FALSE
);
UNICODE_STRING
sectionW
,
entryW
,
def_valW
,
filenameW
;
LPWSTR
bufferW
;
INT16
retW
,
ret
=
0
;
bufferW
=
buffer
?
HeapAlloc
(
GetProcessHeap
(),
0
,
len
*
sizeof
(
WCHAR
))
:
NULL
;
if
(
section
)
RtlCreateUnicodeStringFromAsciiz
(
&
sectionW
,
section
);
else
sectionW
.
Buffer
=
NULL
;
if
(
entry
)
RtlCreateUnicodeStringFromAsciiz
(
&
entryW
,
entry
);
else
entryW
.
Buffer
=
NULL
;
if
(
def_val
)
RtlCreateUnicodeStringFromAsciiz
(
&
def_valW
,
def_val
);
else
def_valW
.
Buffer
=
NULL
;
if
(
filename
)
RtlCreateUnicodeStringFromAsciiz
(
&
filenameW
,
filename
);
else
filenameW
.
Buffer
=
NULL
;
retW
=
PROFILE_GetPrivateProfileString
(
sectionW
.
Buffer
,
entryW
.
Buffer
,
def_valW
.
Buffer
,
bufferW
,
len
,
filenameW
.
Buffer
,
FALSE
);
if
(
len
)
{
ret
=
WideCharToMultiByte
(
CP_ACP
,
0
,
bufferW
,
retW
+
1
,
buffer
,
len
,
NULL
,
NULL
);
if
(
!
ret
)
{
ret
=
len
-
1
;
buffer
[
ret
]
=
0
;
}
else
ret
--
;
/* strip terminating 0 */
}
RtlFreeUnicodeString
(
&
sectionW
);
RtlFreeUnicodeString
(
&
entryW
);
RtlFreeUnicodeString
(
&
def_valW
);
RtlFreeUnicodeString
(
&
filenameW
);
if
(
bufferW
)
HeapFree
(
GetProcessHeap
(),
0
,
bufferW
);
return
ret
;
}
/***********************************************************************
...
...
@@ -1205,8 +1272,41 @@ INT WINAPI GetPrivateProfileStringA( LPCSTR section, LPCSTR entry,
LPCSTR
def_val
,
LPSTR
buffer
,
UINT
len
,
LPCSTR
filename
)
{
return
PROFILE_GetPrivateProfileString
(
section
,
entry
,
def_val
,
buffer
,
len
,
filename
,
TRUE
);
UNICODE_STRING
sectionW
,
entryW
,
def_valW
,
filenameW
;
LPWSTR
bufferW
;
INT
retW
,
ret
=
0
;
bufferW
=
buffer
?
HeapAlloc
(
GetProcessHeap
(),
0
,
len
*
sizeof
(
WCHAR
))
:
NULL
;
if
(
section
)
RtlCreateUnicodeStringFromAsciiz
(
&
sectionW
,
section
);
else
sectionW
.
Buffer
=
NULL
;
if
(
entry
)
RtlCreateUnicodeStringFromAsciiz
(
&
entryW
,
entry
);
else
entryW
.
Buffer
=
NULL
;
if
(
def_val
)
RtlCreateUnicodeStringFromAsciiz
(
&
def_valW
,
def_val
);
else
def_valW
.
Buffer
=
NULL
;
if
(
filename
)
RtlCreateUnicodeStringFromAsciiz
(
&
filenameW
,
filename
);
else
filenameW
.
Buffer
=
NULL
;
retW
=
GetPrivateProfileStringW
(
sectionW
.
Buffer
,
entryW
.
Buffer
,
def_valW
.
Buffer
,
bufferW
,
len
,
filenameW
.
Buffer
);
if
(
len
)
{
ret
=
WideCharToMultiByte
(
CP_ACP
,
0
,
bufferW
,
retW
+
1
,
buffer
,
len
,
NULL
,
NULL
);
if
(
!
ret
)
{
ret
=
len
-
1
;
buffer
[
ret
]
=
0
;
}
else
ret
--
;
/* strip terminating 0 */
}
RtlFreeUnicodeString
(
&
sectionW
);
RtlFreeUnicodeString
(
&
entryW
);
RtlFreeUnicodeString
(
&
def_valW
);
RtlFreeUnicodeString
(
&
filenameW
);
if
(
bufferW
)
HeapFree
(
GetProcessHeap
(),
0
,
bufferW
);
return
ret
;
}
/***********************************************************************
...
...
@@ -1216,21 +1316,8 @@ INT WINAPI GetPrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
LPCWSTR
def_val
,
LPWSTR
buffer
,
UINT
len
,
LPCWSTR
filename
)
{
LPSTR
sectionA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
section
);
LPSTR
entryA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
entry
);
LPSTR
filenameA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
filename
);
LPSTR
def_valA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
def_val
);
LPSTR
bufferA
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
);
INT
ret
=
GetPrivateProfileStringA
(
sectionA
,
entryA
,
def_valA
,
bufferA
,
len
,
filenameA
);
if
(
len
>
0
&&
!
MultiByteToWideChar
(
CP_ACP
,
0
,
bufferA
,
-
1
,
buffer
,
len
))
buffer
[
len
-
1
]
=
0
;
HeapFree
(
GetProcessHeap
(),
0
,
sectionA
);
HeapFree
(
GetProcessHeap
(),
0
,
entryA
);
HeapFree
(
GetProcessHeap
(),
0
,
filenameA
);
HeapFree
(
GetProcessHeap
(),
0
,
def_valA
);
HeapFree
(
GetProcessHeap
(),
0
,
bufferA
);
return
ret
;
return
PROFILE_GetPrivateProfileString
(
section
,
entry
,
def_val
,
buffer
,
len
,
filename
,
TRUE
);
}
/***********************************************************************
...
...
@@ -1239,8 +1326,8 @@ INT WINAPI GetPrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
INT16
WINAPI
GetProfileString16
(
LPCSTR
section
,
LPCSTR
entry
,
LPCSTR
def_val
,
LPSTR
buffer
,
UINT16
len
)
{
return
PROFILE_GetPrivateProfileString
(
section
,
entry
,
def_val
,
buffer
,
len
,
"win.ini"
,
FALSE
);
return
GetPrivateProfileString16
(
section
,
entry
,
def_val
,
buffer
,
len
,
"win.ini"
);
}
/***********************************************************************
...
...
@@ -1249,8 +1336,8 @@ INT16 WINAPI GetProfileString16( LPCSTR section, LPCSTR entry, LPCSTR def_val,
INT
WINAPI
GetProfileStringA
(
LPCSTR
section
,
LPCSTR
entry
,
LPCSTR
def_val
,
LPSTR
buffer
,
UINT
len
)
{
return
PROFILE_GetPrivateProfileString
(
section
,
entry
,
def_val
,
buffer
,
len
,
"win.ini"
,
TRUE
);
return
GetPrivateProfileStringA
(
section
,
entry
,
def_val
,
buffer
,
len
,
"win.ini"
);
}
/***********************************************************************
...
...
@@ -1312,8 +1399,8 @@ UINT WINAPI GetPrivateProfileIntA( LPCSTR section, LPCSTR entry,
char
buffer
[
20
];
long
result
;
if
(
!
PROFILE_GetPrivateProfileString
(
section
,
entry
,
""
,
buffer
,
sizeof
(
buffer
),
filename
,
FALSE
))
if
(
!
GetPrivateProfileStringA
(
section
,
entry
,
""
,
buffer
,
sizeof
(
buffer
),
filename
))
return
def_val
;
/* FIXME: if entry can be found but it's empty, then Win16 is
* supposed to return 0 instead of def_val ! Difficult/problematic
...
...
@@ -1331,6 +1418,8 @@ UINT WINAPI GetPrivateProfileIntA( LPCSTR section, LPCSTR entry,
/***********************************************************************
* GetPrivateProfileIntW (KERNEL32.@)
*
* FIXME: rewrite using unicode
*/
UINT
WINAPI
GetPrivateProfileIntW
(
LPCWSTR
section
,
LPCWSTR
entry
,
INT
def_val
,
LPCWSTR
filename
)
...
...
@@ -1355,10 +1444,10 @@ INT16 WINAPI GetPrivateProfileSection16( LPCSTR section, LPSTR buffer,
}
/***********************************************************************
* GetPrivateProfileSection
A
(KERNEL32.@)
* GetPrivateProfileSection
W
(KERNEL32.@)
*/
INT
WINAPI
GetPrivateProfileSection
A
(
LPCSTR
section
,
LP
STR
buffer
,
DWORD
len
,
LPCSTR
filename
)
INT
WINAPI
GetPrivateProfileSection
W
(
LPCWSTR
section
,
LPW
STR
buffer
,
DWORD
len
,
LPC
W
STR
filename
)
{
int
ret
=
0
;
...
...
@@ -1374,22 +1463,43 @@ INT WINAPI GetPrivateProfileSectionA( LPCSTR section, LPSTR buffer,
}
/***********************************************************************
* GetPrivateProfileSection
W
(KERNEL32.@)
* GetPrivateProfileSection
A
(KERNEL32.@)
*/
INT
WINAPI
GetPrivateProfileSectionA
(
LPCSTR
section
,
LPSTR
buffer
,
DWORD
len
,
LPCSTR
filename
)
{
UNICODE_STRING
sectionW
,
filenameW
;
LPWSTR
bufferW
;
INT
retW
,
ret
=
0
;
INT
WINAPI
GetPrivateProfileSectionW
(
LPCWSTR
section
,
LPWSTR
buffer
,
DWORD
len
,
LPCWSTR
filename
)
bufferW
=
buffer
?
HeapAlloc
(
GetProcessHeap
(),
0
,
len
*
sizeof
(
WCHAR
))
:
NULL
;
if
(
section
)
RtlCreateUnicodeStringFromAsciiz
(
&
sectionW
,
section
);
else
sectionW
.
Buffer
=
NULL
;
if
(
filename
)
RtlCreateUnicodeStringFromAsciiz
(
&
filenameW
,
filename
);
else
filenameW
.
Buffer
=
NULL
;
{
LPSTR
sectionA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
section
);
LPSTR
filenameA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
filename
);
LPSTR
bufferA
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
);
INT
ret
=
GetPrivateProfileSectionA
(
sectionA
,
bufferA
,
len
,
filenameA
);
MultiByteToWideChar
(
CP_ACP
,
0
,
bufferA
,
ret
,
buffer
,
len
);
HeapFree
(
GetProcessHeap
(),
0
,
sectionA
);
HeapFree
(
GetProcessHeap
(),
0
,
filenameA
);
HeapFree
(
GetProcessHeap
(),
0
,
bufferA
);
retW
=
GetPrivateProfileSectionW
(
sectionW
.
Buffer
,
bufferW
,
len
,
filenameW
.
Buffer
);
if
(
len
>
2
)
{
ret
=
WideCharToMultiByte
(
CP_ACP
,
0
,
bufferW
,
retW
+
2
,
buffer
,
len
,
NULL
,
NULL
);
if
(
ret
>
2
)
ret
-=
2
;
else
{
ret
=
0
;
buffer
[
len
-
2
]
=
0
;
buffer
[
len
-
1
]
=
0
;
}
}
else
{
buffer
[
0
]
=
0
;
buffer
[
1
]
=
0
;
}
RtlFreeUnicodeString
(
&
sectionW
);
RtlFreeUnicodeString
(
&
filenameW
);
if
(
bufferW
)
HeapFree
(
GetProcessHeap
(),
0
,
bufferW
);
return
ret
;
}
...
...
@@ -1428,10 +1538,10 @@ BOOL16 WINAPI WritePrivateProfileString16( LPCSTR section, LPCSTR entry,
}
/***********************************************************************
* WritePrivateProfileString
A
(KERNEL32.@)
* WritePrivateProfileString
W
(KERNEL32.@)
*/
BOOL
WINAPI
WritePrivateProfileString
A
(
LPCSTR
section
,
LPC
STR
entry
,
LPC
STR
string
,
LPC
STR
filename
)
BOOL
WINAPI
WritePrivateProfileString
W
(
LPCWSTR
section
,
LPCW
STR
entry
,
LPC
WSTR
string
,
LPCW
STR
filename
)
{
BOOL
ret
=
FALSE
;
...
...
@@ -1440,12 +1550,17 @@ BOOL WINAPI WritePrivateProfileStringA( LPCSTR section, LPCSTR entry,
if
(
PROFILE_Open
(
filename
))
{
if
(
!
section
&&
!
entry
&&
!
string
)
/* documented "file flush" case */
{
PROFILE_FlushFile
();
PROFILE_ReleaseFile
();
/* always return FALSE in this case */
}
else
{
if
(
!
section
)
{
FIXME
(
"(NULL?,%s,%s,%s)?
\n
"
,
entry
,
string
,
filename
);
FIXME
(
"(NULL?,%s,%s,%s)?
\n
"
,
debugstr_w
(
entry
),
debugstr_w
(
string
),
debugstr_w
(
filename
));
}
else
{
ret
=
PROFILE_SetString
(
section
,
entry
,
string
,
FALSE
);
PROFILE_FlushFile
();
}
}
}
...
...
@@ -1455,22 +1570,30 @@ BOOL WINAPI WritePrivateProfileStringA( LPCSTR section, LPCSTR entry,
}
/***********************************************************************
* WritePrivateProfileString
W
(KERNEL32.@)
* WritePrivateProfileString
A
(KERNEL32.@)
*/
BOOL
WINAPI
WritePrivateProfileString
W
(
LPCWSTR
section
,
LPCW
STR
entry
,
LPC
WSTR
string
,
LPCW
STR
filename
)
BOOL
WINAPI
WritePrivateProfileString
A
(
LPCSTR
section
,
LPC
STR
entry
,
LPC
STR
string
,
LPC
STR
filename
)
{
LPSTR
sectionA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
section
);
LPSTR
entryA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
entry
);
LPSTR
stringA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
string
);
LPSTR
filenameA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
filename
);
BOOL
res
=
WritePrivateProfileStringA
(
sectionA
,
entryA
,
stringA
,
filenameA
);
HeapFree
(
GetProcessHeap
(),
0
,
sectionA
);
HeapFree
(
GetProcessHeap
(),
0
,
entryA
);
HeapFree
(
GetProcessHeap
(),
0
,
stringA
);
HeapFree
(
GetProcessHeap
(),
0
,
filenameA
);
return
res
;
UNICODE_STRING
sectionW
,
entryW
,
stringW
,
filenameW
;
BOOL
ret
;
if
(
section
)
RtlCreateUnicodeStringFromAsciiz
(
&
sectionW
,
section
);
else
sectionW
.
Buffer
=
NULL
;
if
(
entry
)
RtlCreateUnicodeStringFromAsciiz
(
&
entryW
,
entry
);
else
entryW
.
Buffer
=
NULL
;
if
(
string
)
RtlCreateUnicodeStringFromAsciiz
(
&
stringW
,
string
);
else
stringW
.
Buffer
=
NULL
;
if
(
filename
)
RtlCreateUnicodeStringFromAsciiz
(
&
filenameW
,
filename
);
else
filenameW
.
Buffer
=
NULL
;
ret
=
WritePrivateProfileStringW
(
sectionW
.
Buffer
,
entryW
.
Buffer
,
stringW
.
Buffer
,
filenameW
.
Buffer
);
RtlFreeUnicodeString
(
&
sectionW
);
RtlFreeUnicodeString
(
&
entryW
);
RtlFreeUnicodeString
(
&
stringW
);
RtlFreeUnicodeString
(
&
filenameW
);
return
ret
;
}
/***********************************************************************
...
...
@@ -1483,34 +1606,36 @@ BOOL16 WINAPI WritePrivateProfileSection16( LPCSTR section,
}
/***********************************************************************
* WritePrivateProfileSection
A
(KERNEL32.@)
* WritePrivateProfileSection
W
(KERNEL32.@)
*/
BOOL
WINAPI
WritePrivateProfileSection
A
(
LPC
STR
section
,
LPCSTR
string
,
LPC
STR
filename
)
BOOL
WINAPI
WritePrivateProfileSection
W
(
LPCW
STR
section
,
LPCWSTR
string
,
LPCW
STR
filename
)
{
BOOL
ret
=
FALSE
;
LP
STR
p
;
LP
WSTR
p
;
EnterCriticalSection
(
&
PROFILE_CritSect
);
if
(
PROFILE_Open
(
filename
))
{
if
(
!
section
&&
!
string
)
PROFILE_ReleaseFile
();
/* always return FALSE in this case */
else
if
(
!
string
)
/* delete the named section*/
else
if
(
!
string
)
{
/* delete the named section*/
ret
=
PROFILE_SetString
(
section
,
NULL
,
NULL
,
FALSE
);
else
{
PROFILE_FlushFile
();
}
else
{
PROFILE_DeleteAllKeys
(
section
);
ret
=
TRUE
;
while
(
*
string
)
{
LPSTR
buf
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlen
(
string
)
+
1
);
strcpy
(
buf
,
string
);
if
((
p
=
strchr
(
buf
,
'='
)))
{
LPWSTR
buf
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
strlenW
(
string
)
+
1
)
*
sizeof
(
WCHAR
)
);
strcpy
W
(
buf
,
string
);
if
((
p
=
strchrW
(
buf
,
'='
)))
{
*
p
=
'\0'
;
ret
=
PROFILE_SetString
(
section
,
buf
,
p
+
1
,
TRUE
);
}
HeapFree
(
GetProcessHeap
(),
0
,
buf
);
string
+=
strlen
(
string
)
+
1
;
string
+=
strlen
W
(
string
)
+
1
;
}
PROFILE_FlushFile
();
}
}
...
...
@@ -1519,20 +1644,39 @@ BOOL WINAPI WritePrivateProfileSectionA( LPCSTR section,
}
/***********************************************************************
* WritePrivateProfileSection
W
(KERNEL32.@)
* WritePrivateProfileSection
A
(KERNEL32.@)
*/
BOOL
WINAPI
WritePrivateProfileSection
W
(
LPCW
STR
section
,
LPCWSTR
string
,
LPCW
STR
filename
)
BOOL
WINAPI
WritePrivateProfileSection
A
(
LPC
STR
section
,
LPCSTR
string
,
LPC
STR
filename
)
{
LPSTR
sectionA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
section
);
LPSTR
stringA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
string
);
LPSTR
filenameA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
filename
);
BOOL
res
=
WritePrivateProfileSectionA
(
sectionA
,
stringA
,
filenameA
);
HeapFree
(
GetProcessHeap
(),
0
,
sectionA
);
HeapFree
(
GetProcessHeap
(),
0
,
stringA
);
HeapFree
(
GetProcessHeap
(),
0
,
filenameA
);
return
res
;
UNICODE_STRING
sectionW
,
filenameW
;
LPWSTR
stringW
;
BOOL
ret
;
if
(
string
)
{
INT
lenA
,
lenW
;
LPCSTR
p
=
string
;
while
(
*
p
)
p
+=
strlen
(
p
)
+
1
;
lenA
=
p
-
string
+
1
;
lenW
=
MultiByteToWideChar
(
CP_ACP
,
0
,
string
,
lenA
,
NULL
,
0
);
if
((
stringW
=
HeapAlloc
(
GetProcessHeap
(),
0
,
lenW
*
sizeof
(
WCHAR
))))
MultiByteToWideChar
(
CP_ACP
,
0
,
string
,
lenA
,
stringW
,
lenW
);
}
else
stringW
=
NULL
;
if
(
section
)
RtlCreateUnicodeStringFromAsciiz
(
&
sectionW
,
section
);
else
sectionW
.
Buffer
=
NULL
;
if
(
filename
)
RtlCreateUnicodeStringFromAsciiz
(
&
filenameW
,
filename
);
else
filenameW
.
Buffer
=
NULL
;
ret
=
WritePrivateProfileSectionW
(
sectionW
.
Buffer
,
stringW
,
filenameW
.
Buffer
);
HeapFree
(
GetProcessHeap
(),
0
,
stringW
);
RtlFreeUnicodeString
(
&
sectionW
);
RtlFreeUnicodeString
(
&
filenameW
);
return
ret
;
}
/***********************************************************************
...
...
@@ -1557,7 +1701,7 @@ BOOL WINAPI WriteProfileSectionA( LPCSTR section, LPCSTR keys_n_values)
*/
BOOL
WINAPI
WriteProfileSectionW
(
LPCWSTR
section
,
LPCWSTR
keys_n_values
)
{
return
(
WritePrivateProfileSectionW
(
section
,
keys_n_values
,
wininiW
)
);
return
WritePrivateProfileSectionW
(
section
,
keys_n_values
,
wininiW
);
}
/***********************************************************************
...
...
@@ -1581,7 +1725,7 @@ WORD WINAPI GetProfileSectionNames16(LPSTR buffer, WORD size)
/***********************************************************************
* GetPrivateProfileSectionNames
A
(KERNEL32.@)
* GetPrivateProfileSectionNames
W
(KERNEL32.@)
*
* Returns the section names contained in the specified file.
* FIXME: Where do we find this file when the path is relative?
...
...
@@ -1617,9 +1761,8 @@ WORD WINAPI GetProfileSectionNames16(LPSTR buffer, WORD size)
* Note that when the buffer is big enough then the return value may be any
* value between 1 and len-1 (or len in Win95), including len-2.
*/
DWORD
WINAPI
GetPrivateProfileSectionNamesA
(
LPSTR
buffer
,
DWORD
size
,
LPCSTR
filename
)
DWORD
WINAPI
GetPrivateProfileSectionNamesW
(
LPWSTR
buffer
,
DWORD
size
,
LPCWSTR
filename
)
{
DWORD
ret
=
0
;
...
...
@@ -1635,21 +1778,32 @@ DWORD WINAPI GetPrivateProfileSectionNamesA( LPSTR buffer, DWORD size,
/***********************************************************************
* GetPrivateProfileSectionNames
W
(KERNEL32.@)
* GetPrivateProfileSectionNames
A
(KERNEL32.@)
*/
DWORD
WINAPI
GetPrivateProfileSectionNamesW
(
LPWSTR
buffer
,
DWORD
size
,
LPCWSTR
filename
)
DWORD
WINAPI
GetPrivateProfileSectionNamesA
(
LPSTR
buffer
,
DWORD
size
,
LPCSTR
filename
)
{
LPSTR
filenameA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
filename
);
LPSTR
bufferA
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
);
UNICODE_STRING
filenameW
;
LPWSTR
bufferW
;
INT
retW
,
ret
=
0
;
INT
ret
=
GetPrivateProfileSectionNamesA
(
bufferA
,
size
,
filenameA
);
if
(
size
>
0
&&
!
MultiByteToWideChar
(
CP_ACP
,
0
,
bufferA
,
-
1
,
buffer
,
size
))
buffer
[
size
-
1
]
=
0
;
HeapFree
(
GetProcessHeap
(),
0
,
bufferA
);
HeapFree
(
GetProcessHeap
(),
0
,
filenameA
);
bufferW
=
buffer
?
HeapAlloc
(
GetProcessHeap
(),
0
,
size
*
sizeof
(
WCHAR
))
:
NULL
;
if
(
filename
)
RtlCreateUnicodeStringFromAsciiz
(
&
filenameW
,
filename
);
else
filenameW
.
Buffer
=
NULL
;
retW
=
GetPrivateProfileSectionNamesW
(
bufferW
,
size
,
filenameW
.
Buffer
);
if
(
retW
&&
size
)
{
ret
=
WideCharToMultiByte
(
CP_ACP
,
0
,
bufferW
,
retW
,
buffer
,
size
,
NULL
,
NULL
);
if
(
!
ret
)
{
ret
=
size
;
buffer
[
size
-
1
]
=
0
;
}
}
RtlFreeUnicodeString
(
&
filenameW
);
if
(
bufferW
)
HeapFree
(
GetProcessHeap
(),
0
,
bufferW
);
return
ret
;
}
...
...
@@ -1663,12 +1817,12 @@ BOOL16 WINAPI GetPrivateProfileStruct16(LPCSTR section, LPCSTR key,
}
/***********************************************************************
* GetPrivateProfileStruct
A
(KERNEL32.@)
* GetPrivateProfileStruct
W
(KERNEL32.@)
*
* Should match Win95's behaviour pretty much
*/
BOOL
WINAPI
GetPrivateProfileStruct
A
(
LPCSTR
section
,
LPC
STR
key
,
LPVOID
buf
,
UINT
len
,
LPC
STR
filename
)
BOOL
WINAPI
GetPrivateProfileStruct
W
(
LPCWSTR
section
,
LPCW
STR
key
,
LPVOID
buf
,
UINT
len
,
LPCW
STR
filename
)
{
BOOL
ret
=
FALSE
;
...
...
@@ -1677,22 +1831,22 @@ BOOL WINAPI GetPrivateProfileStructA (LPCSTR section, LPCSTR key,
if
(
PROFILE_Open
(
filename
))
{
PROFILEKEY
*
k
=
PROFILE_Find
(
&
CurProfile
->
section
,
section
,
key
,
FALSE
,
FALSE
);
if
(
k
)
{
TRACE
(
"value (at %p):
'%s'
\n
"
,
k
->
value
,
k
->
value
);
if
(((
strlen
(
k
->
value
)
-
2
)
/
2
)
==
len
)
TRACE
(
"value (at %p):
%s
\n
"
,
k
->
value
,
debugstr_w
(
k
->
value
)
);
if
(((
strlen
W
(
k
->
value
)
-
2
)
/
2
)
==
len
)
{
LPSTR
end
,
p
;
LP
W
STR
end
,
p
;
BOOL
valid
=
TRUE
;
CHAR
c
;
W
CHAR
c
;
DWORD
chksum
=
0
;
end
=
k
->
value
+
strlen
(
k
->
value
);
/* -> '\0' */
end
=
k
->
value
+
strlen
W
(
k
->
value
);
/* -> '\0' */
/* check for invalid chars in ASCII coded hex string */
for
(
p
=
k
->
value
;
p
<
end
;
p
++
)
{
if
(
!
isxdigit
(
*
p
))
if
(
!
isxdigit
W
(
*
p
))
{
WARN
(
"invalid char '%
c' in file '%s'->'[%s]'->'%s'
!
\n
"
,
*
p
,
filename
,
section
,
key
);
WARN
(
"invalid char '%
x' in file %s->[%s]->%s
!
\n
"
,
*
p
,
debugstr_w
(
filename
),
debugstr_w
(
section
),
debugstr_w
(
key
)
);
valid
=
FALSE
;
break
;
}
...
...
@@ -1707,7 +1861,7 @@ BOOL WINAPI GetPrivateProfileStructA (LPCSTR section, LPCSTR key,
/* translate ASCII hex format into binary data */
for
(
p
=
k
->
value
;
p
<
end
;
p
++
)
{
c
=
toupper
(
*
p
);
c
=
toupper
W
(
*
p
);
val
=
(
c
>
'9'
)
?
(
c
-
'A'
+
10
)
:
(
c
-
'0'
);
...
...
@@ -1722,9 +1876,9 @@ BOOL WINAPI GetPrivateProfileStructA (LPCSTR section, LPCSTR key,
highnibble
^=
1
;
/* toggle */
}
/* retrieve stored checksum value */
c
=
toupper
(
*
p
++
);
c
=
toupper
W
(
*
p
++
);
b
=
(
(
c
>
'9'
)
?
(
c
-
'A'
+
10
)
:
(
c
-
'0'
)
)
<<
4
;
c
=
toupper
(
*
p
);
c
=
toupper
W
(
*
p
);
b
+=
(
c
>
'9'
)
?
(
c
-
'A'
+
10
)
:
(
c
-
'0'
);
if
(
b
==
(
chksum
&
0xff
))
/* checksums match ? */
ret
=
TRUE
;
...
...
@@ -1738,25 +1892,28 @@ BOOL WINAPI GetPrivateProfileStructA (LPCSTR section, LPCSTR key,
}
/***********************************************************************
* GetPrivateProfileStruct
W
(KERNEL32.@)
* GetPrivateProfileStruct
A
(KERNEL32.@)
*/
BOOL
WINAPI
GetPrivateProfileStruct
W
(
LPCWSTR
section
,
LPCW
STR
key
,
LPVOID
buffer
,
UINT
len
,
LPC
W
STR
filename
)
BOOL
WINAPI
GetPrivateProfileStruct
A
(
LPCSTR
section
,
LPC
STR
key
,
LPVOID
buffer
,
UINT
len
,
LPCSTR
filename
)
{
LPSTR
sectionA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
section
);
LPSTR
keyA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
key
);
LPSTR
filenameA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
filename
);
LPSTR
bufferA
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
);
UNICODE_STRING
sectionW
,
keyW
,
filenameW
;
INT
ret
;
INT
ret
=
GetPrivateProfileStructA
(
sectionA
,
keyA
,
bufferA
,
len
,
filenameA
);
if
(
len
>
0
&&
!
MultiByteToWideChar
(
CP_ACP
,
0
,
bufferA
,
-
1
,
buffer
,
len
))
((
LPWSTR
)
buffer
)[
len
-
1
]
=
0
;
HeapFree
(
GetProcessHeap
(),
0
,
bufferA
);
HeapFree
(
GetProcessHeap
(),
0
,
sectionA
);
HeapFree
(
GetProcessHeap
(),
0
,
keyA
);
HeapFree
(
GetProcessHeap
(),
0
,
filenameA
);
if
(
section
)
RtlCreateUnicodeStringFromAsciiz
(
&
sectionW
,
section
);
else
sectionW
.
Buffer
=
NULL
;
if
(
key
)
RtlCreateUnicodeStringFromAsciiz
(
&
keyW
,
key
);
else
keyW
.
Buffer
=
NULL
;
if
(
filename
)
RtlCreateUnicodeStringFromAsciiz
(
&
filenameW
,
filename
);
else
filenameW
.
Buffer
=
NULL
;
ret
=
GetPrivateProfileStructW
(
sectionW
.
Buffer
,
keyW
.
Buffer
,
buffer
,
len
,
filenameW
.
Buffer
);
/* Do not translate binary data. */
RtlFreeUnicodeString
(
&
sectionW
);
RtlFreeUnicodeString
(
&
keyW
);
RtlFreeUnicodeString
(
&
filenameW
);
return
ret
;
}
...
...
@@ -1772,21 +1929,21 @@ BOOL16 WINAPI WritePrivateProfileStruct16 (LPCSTR section, LPCSTR key,
}
/***********************************************************************
* WritePrivateProfileStruct
A
(KERNEL32.@)
* WritePrivateProfileStruct
W
(KERNEL32.@)
*/
BOOL
WINAPI
WritePrivateProfileStruct
A
(
LPCSTR
section
,
LPC
STR
key
,
LPVOID
buf
,
UINT
bufsize
,
LPCSTR
filename
)
BOOL
WINAPI
WritePrivateProfileStruct
W
(
LPCWSTR
section
,
LPCW
STR
key
,
LPVOID
buf
,
UINT
bufsize
,
LPC
W
STR
filename
)
{
BOOL
ret
=
FALSE
;
LPBYTE
binbuf
;
LPSTR
outstring
,
p
;
LP
W
STR
outstring
,
p
;
DWORD
sum
=
0
;
if
(
!
section
&&
!
key
&&
!
buf
)
/* flush the cache */
return
WritePrivateProfileString
A
(
NULL
,
NULL
,
NULL
,
filename
);
return
WritePrivateProfileString
W
(
NULL
,
NULL
,
NULL
,
filename
);
/* allocate string buffer for hex chars + checksum hex char + '\0' */
outstring
=
HeapAlloc
(
GetProcessHeap
(),
0
,
bufsize
*
2
+
2
+
1
);
outstring
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
bufsize
*
2
+
2
+
1
)
*
sizeof
(
WCHAR
)
);
p
=
outstring
;
for
(
binbuf
=
(
LPBYTE
)
buf
;
binbuf
<
(
LPBYTE
)
buf
+
bufsize
;
binbuf
++
)
{
*
p
++
=
hex
[
*
binbuf
>>
4
];
...
...
@@ -1800,8 +1957,10 @@ BOOL WINAPI WritePrivateProfileStructA (LPCSTR section, LPCSTR key,
EnterCriticalSection
(
&
PROFILE_CritSect
);
if
(
PROFILE_Open
(
filename
))
if
(
PROFILE_Open
(
filename
))
{
ret
=
PROFILE_SetString
(
section
,
key
,
outstring
,
FALSE
);
PROFILE_FlushFile
();
}
LeaveCriticalSection
(
&
PROFILE_CritSect
);
...
...
@@ -1811,20 +1970,28 @@ BOOL WINAPI WritePrivateProfileStructA (LPCSTR section, LPCSTR key,
}
/***********************************************************************
* WritePrivateProfileStruct
W
(KERNEL32.@)
* WritePrivateProfileStruct
A
(KERNEL32.@)
*/
BOOL
WINAPI
WritePrivateProfileStruct
W
(
LPCWSTR
section
,
LPCW
STR
key
,
LPVOID
buf
,
UINT
bufsize
,
LPC
W
STR
filename
)
BOOL
WINAPI
WritePrivateProfileStruct
A
(
LPCSTR
section
,
LPC
STR
key
,
LPVOID
buf
,
UINT
bufsize
,
LPCSTR
filename
)
{
LPSTR
sectionA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
section
);
LPSTR
keyA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
key
);
LPSTR
filenameA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
filename
);
INT
ret
=
WritePrivateProfileStructA
(
sectionA
,
keyA
,
buf
,
bufsize
,
filenameA
);
HeapFree
(
GetProcessHeap
(),
0
,
sectionA
);
HeapFree
(
GetProcessHeap
(),
0
,
keyA
);
HeapFree
(
GetProcessHeap
(),
0
,
filenameA
);
UNICODE_STRING
sectionW
,
keyW
,
filenameW
;
INT
ret
;
if
(
section
)
RtlCreateUnicodeStringFromAsciiz
(
&
sectionW
,
section
);
else
sectionW
.
Buffer
=
NULL
;
if
(
key
)
RtlCreateUnicodeStringFromAsciiz
(
&
keyW
,
key
);
else
keyW
.
Buffer
=
NULL
;
if
(
filename
)
RtlCreateUnicodeStringFromAsciiz
(
&
filenameW
,
filename
);
else
filenameW
.
Buffer
=
NULL
;
/* Do not translate binary data. */
ret
=
WritePrivateProfileStructW
(
sectionW
.
Buffer
,
keyW
.
Buffer
,
buf
,
bufsize
,
filenameW
.
Buffer
);
RtlFreeUnicodeString
(
&
sectionW
);
RtlFreeUnicodeString
(
&
keyW
);
RtlFreeUnicodeString
(
&
filenameW
);
return
ret
;
}
...
...
files/smb.c
View file @
d75aed2c
...
...
@@ -1392,7 +1392,7 @@ static HANDLE SMB_RegisterFile( int fd, USHORT tree_id, USHORT user_id, USHORT d
return
ret
;
}
HANDLE
WINAPI
SMB_CreateFile
A
(
LPC
STR
uncname
,
DWORD
access
,
DWORD
sharing
,
HANDLE
WINAPI
SMB_CreateFile
W
(
LPCW
STR
uncname
,
DWORD
access
,
DWORD
sharing
,
LPSECURITY_ATTRIBUTES
sa
,
DWORD
creation
,
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
;
LPSTR
name
,
host
,
share
,
file
;
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
)
return
handle
;
lstrcpyA
(
name
,
uncname
);
WideCharToMultiByte
(
CP_ACP
,
0
,
uncname
,
-
1
,
name
,
len
,
NULL
,
NULL
);
if
(
!
UNC_SplitName
(
name
,
&
host
,
&
share
,
&
file
)
)
{
...
...
@@ -1545,21 +1547,22 @@ BOOL WINAPI SMB_ReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, LPDWORD
return
r
;
}
SMB_DIR
*
WINAPI
SMB_FindFirst
(
LPCSTR
name
)
SMB_DIR
*
WINAPI
SMB_FindFirst
(
LPC
W
STR
name
)
{
int
fd
=
-
1
;
LPSTR
host
,
share
,
file
;
USHORT
tree_id
=
0
,
user_id
=
0
,
dialect
=
0
;
SMB_DIR
*
ret
=
NULL
;
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
)
return
ret
;
lstrcpyA
(
filename
,
name
);
WideCharToMultiByte
(
CP_ACP
,
0
,
name
,
-
1
,
filename
,
len
,
NULL
,
NULL
);
if
(
!
UNC_SplitName
(
filename
,
&
host
,
&
share
,
&
file
)
)
goto
done
;
...
...
@@ -1587,7 +1590,7 @@ done:
}
BOOL
WINAPI
SMB_FindNext
(
SMB_DIR
*
dir
,
WIN32_FIND_DATA
A
*
data
)
BOOL
WINAPI
SMB_FindNext
(
SMB_DIR
*
dir
,
WIN32_FIND_DATA
W
*
data
)
{
unsigned
char
*
ent
;
int
len
,
fnlen
;
...
...
@@ -1613,14 +1616,16 @@ BOOL WINAPI SMB_FindNext(SMB_DIR *dir, WIN32_FIND_DATAA *data )
/* copy the long filename */
fnlen
=
SMB_GETDWORD
(
&
ent
[
0x3c
]);
if
(
fnlen
>
(
sizeof
data
->
cFileName
/
sizeof
(
CHAR
))
)
if
(
fnlen
>
(
sizeof
data
->
cFileName
/
sizeof
(
W
CHAR
))
)
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 */
if
(
ent
[
0x44
]
>
(
sizeof
data
->
cAlternateFileName
/
sizeof
(
CHAR
))
)
if
(
ent
[
0x44
]
>
(
sizeof
data
->
cAlternateFileName
/
sizeof
(
W
CHAR
))
)
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
++
;
...
...
files/smb.h
View file @
d75aed2c
...
...
@@ -96,7 +96,7 @@
#define TRANS2_FIND_NEXT2 0x02
extern
BOOL
WINAPI
SMB_ReadFile
(
HANDLE
hFile
,
LPVOID
buffer
,
DWORD
bytesToRead
,
LPDWORD
bytesRead
,
LPOVERLAPPED
lpOverlapped
);
extern
HANDLE
WINAPI
SMB_CreateFile
A
(
LPC
STR
filename
,
DWORD
access
,
DWORD
sharing
,
extern
HANDLE
WINAPI
SMB_CreateFile
W
(
LPCW
STR
filename
,
DWORD
access
,
DWORD
sharing
,
LPSECURITY_ATTRIBUTES
sa
,
DWORD
creation
,
DWORD
attributes
,
HANDLE
template
);
...
...
@@ -108,8 +108,8 @@ typedef struct tagSMB_DIR
unsigned
char
*
buffer
;
}
SMB_DIR
;
extern
SMB_DIR
*
WINAPI
SMB_FindFirst
(
LPCSTR
filename
);
extern
BOOL
WINAPI
SMB_FindNext
(
SMB_DIR
*
dir
,
WIN32_FIND_DATA
A
*
data
);
extern
SMB_DIR
*
WINAPI
SMB_FindFirst
(
LPC
W
STR
filename
);
extern
BOOL
WINAPI
SMB_FindNext
(
SMB_DIR
*
dir
,
WIN32_FIND_DATA
W
*
data
);
extern
BOOL
WINAPI
SMB_CloseDir
(
SMB_DIR
*
dir
);
#endif
/* __INC_SMB__ */
include/drive.h
View file @
d75aed2c
...
...
@@ -39,15 +39,17 @@ extern int DRIVE_IsValid( int drive );
extern
int
DRIVE_GetCurrentDrive
(
void
);
extern
int
DRIVE_SetCurrentDrive
(
int
drive
);
extern
int
DRIVE_FindDriveRoot
(
const
char
**
path
);
extern
int
DRIVE_FindDriveRootW
(
LPCWSTR
*
path
);
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_GetDevice
(
int
drive
);
extern
const
char
*
DRIVE_GetLabel
(
int
drive
);
extern
LPCWSTR
DRIVE_GetLabel
(
int
drive
);
extern
DWORD
DRIVE_GetSerialNumber
(
int
drive
);
extern
int
DRIVE_SetSerialNumber
(
int
drive
,
DWORD
serial
);
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_Enable
(
int
drive
);
extern
int
DRIVE_SetLogicalMapping
(
int
existing_drive
,
int
new_drive
);
...
...
include/file.h
View file @
d75aed2c
...
...
@@ -26,6 +26,7 @@
#include <sys/types.h>
#include "winbase.h"
#include "wine/windef16.h"
/* HFILE16 */
#include "wine/unicode.h"
#define MAX_PATHNAME_LEN 1024
...
...
@@ -33,7 +34,7 @@
typedef
struct
{
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
;
}
DOS_FULL_NAME
;
...
...
@@ -42,8 +43,9 @@ typedef struct
/* DOS device descriptor */
typedef
struct
{
c
har
*
name
;
c
onst
WCHAR
name
[
9
]
;
int
flags
;
UINT
codepage
;
}
DOS_DEVICE
;
/* locale-independent case conversion */
...
...
@@ -64,6 +66,12 @@ inline static int FILE_contains_path (LPCSTR name)
strchr
(
name
,
'/'
)
||
strchr
(
name
,
'\\'
));
}
inline
static
int
FILE_contains_pathW
(
LPCWSTR
name
)
{
return
((
*
name
&&
(
name
[
1
]
==
':'
))
||
strchrW
(
name
,
'/'
)
||
strchrW
(
name
,
'\\'
));
}
/* files/file.c */
extern
mode_t
FILE_umask
;
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
DWORD
DIR_SearchAlternatePath
(
LPCSTR
dll_path
,
LPCSTR
name
,
LPCSTR
ext
,
DWORD
buflen
,
LPSTR
buffer
,
LPSTR
*
lastpart
);
extern
DWORD
DIR_SearchPath
(
LPC
STR
path
,
LPCSTR
name
,
LPC
STR
ext
,
extern
DWORD
DIR_SearchPath
(
LPC
WSTR
path
,
LPCWSTR
name
,
LPCW
STR
ext
,
DOS_FULL_NAME
*
full_name
,
BOOL
win32
);
/* files/dos_fs.c */
extern
void
DOSFS_UnixTimeToFileTime
(
time_t
unixtime
,
LPFILETIME
ft
,
DWORD
remainder
);
extern
time_t
DOSFS_FileTimeToUnixTime
(
const
FILETIME
*
ft
,
DWORD
*
remainder
);
extern
BOOL
DOSFS_ToDosFCBFormat
(
LPC
STR
name
,
LP
STR
buffer
);
extern
const
DOS_DEVICE
*
DOSFS_GetDevice
(
const
char
*
name
);
extern
BOOL
DOSFS_ToDosFCBFormat
(
LPC
WSTR
name
,
LPW
STR
buffer
);
extern
const
DOS_DEVICE
*
DOSFS_GetDevice
(
LPCWSTR
name
);
extern
const
DOS_DEVICE
*
DOSFS_GetDeviceByHandle
(
HANDLE
hFile
);
extern
HANDLE
DOSFS_OpenDevice
(
const
char
*
name
,
DWORD
access
,
DWORD
attributes
,
LPSECURITY_ATTRIBUTES
sa
);
extern
BOOL
DOSFS_FindUnixName
(
LPCSTR
path
,
LPCSTR
name
,
LPSTR
long_buf
,
INT
long_len
,
LPSTR
short_buf
,
BOOL
ignore_case
);
extern
BOOL
DOSFS_GetFullName
(
LPCSTR
name
,
BOOL
check_last
,
extern
HANDLE
DOSFS_OpenDevice
(
LPCWSTR
name
,
DWORD
access
,
DWORD
attributes
,
LPSECURITY_ATTRIBUTES
sa
);
extern
BOOL
DOSFS_FindUnixName
(
const
DOS_FULL_NAME
*
path
,
LPCWSTR
name
,
char
*
long_buf
,
INT
long_len
,
LPWSTR
short_buf
,
BOOL
ignore_case
);
extern
BOOL
DOSFS_GetFullName
(
LPCWSTR
name
,
BOOL
check_last
,
DOS_FULL_NAME
*
full
);
extern
int
DOSFS_FindNext
(
const
char
*
path
,
const
char
*
short_mask
,
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 */
extern
int
PROFILE_LoadWineIni
(
void
);
extern
void
PROFILE_UsageWineIni
(
void
);
extern
int
PROFILE_GetWineIniString
(
const
char
*
section
,
const
char
*
key_name
,
const
char
*
def
,
char
*
buffer
,
int
len
);
extern
int
PROFILE_GetWineIniBool
(
char
const
*
section
,
char
const
*
key_name
,
int
def
);
extern
int
PROFILE_GetWineIniString
(
LPCWSTR
section
,
LPCWSTR
key_name
,
LPCWSTR
def
,
LPWSTR
buffer
,
int
len
);
extern
int
PROFILE_GetWineIniBool
(
LPCWSTR
section
,
LPCWSTR
key_name
,
int
def
);
/* win32/device.c */
extern
HANDLE
DEVICE_Open
(
LPCSTR
filename
,
DWORD
access
,
LPSECURITY_ATTRIBUTES
sa
);
extern
HANDLE
DEVICE_Open
(
LPC
W
STR
filename
,
DWORD
access
,
LPSECURITY_ATTRIBUTES
sa
);
/* ntdll/cdrom.c.c */
extern
BOOL
CDROM_DeviceIoControl
(
DWORD
clientID
,
HANDLE
hDevice
,
DWORD
dwIoControlCode
,
...
...
loader/task.c
View file @
d75aed2c
...
...
@@ -290,8 +290,9 @@ static TDB *TASK_Create( NE_MODULE *pModule, UINT16 cmdShow, TEB *teb, LPCSTR cm
pTask
->
teb
=
teb
;
pTask
->
curdrive
=
DRIVE_GetCurrentDrive
()
|
0x80
;
strcpy
(
pTask
->
curdir
,
"
\\
"
);
lstrcpynA
(
pTask
->
curdir
+
1
,
DRIVE_GetDosCwd
(
DRIVE_GetCurrentDrive
()
),
sizeof
(
pTask
->
curdir
)
-
1
);
WideCharToMultiByte
(
CP_ACP
,
0
,
DRIVE_GetDosCwd
(
DRIVE_GetCurrentDrive
()),
-
1
,
pTask
->
curdir
+
1
,
sizeof
(
pTask
->
curdir
)
-
1
,
NULL
,
NULL
);
pTask
->
curdir
[
sizeof
(
pTask
->
curdir
)
-
1
]
=
0
;
/* ensure 0 termination */
/* Create the thunks block */
...
...
memory/registry.c
View file @
d75aed2c
...
...
@@ -46,11 +46,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(reg);
/* 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
);
}
/* check if current version is NT or Win95 */
inline
static
int
is_version_nt
(
void
)
{
return
!
(
GetVersion
()
&
0x80000000
);
}
/******************************************************************************
* RegCreateKeyExA [ADVAPI32.@]
...
...
@@ -91,6 +96,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.@]
*/
DWORD
WINAPI
RegCreateKeyA
(
HKEY
hkey
,
LPCSTR
name
,
LPHKEY
retkey
)
...
...
@@ -102,6 +128,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.@]
*/
DWORD
WINAPI
RegOpenKeyExA
(
HKEY
hkey
,
LPCSTR
name
,
DWORD
reserved
,
REGSAM
access
,
LPHKEY
retkey
)
...
...
@@ -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
,
reserved
,
subkeys
,
max_subkey
,
values
,
max_value
,
max_data
,
security
,
modif
);
if
(
class
&&
!
class_len
&&
!
(
GetVersion
()
&
0x80000000
/*NT*/
))
return
ERROR_INVALID_PARAMETER
;
if
(
class
&&
!
class_len
&&
is_version_nt
())
return
ERROR_INVALID_PARAMETER
;
status
=
NtQueryKey
(
hkey
,
KeyFullInformation
,
buffer
,
sizeof
(
buffer
),
&
total_size
);
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.@]
...
...
@@ -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.@]
...
...
@@ -715,3 +899,56 @@ done:
SetLastError
(
err
);
/* restore last error code */
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
;
}
misc/registry.c
View file @
d75aed2c
...
...
@@ -1050,16 +1050,21 @@ static void _init_registry_saving( HKEY hkey_users_default )
{
int
all
;
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
);
PROFILE_GetWineIniString
(
"registry"
,
"PeriodicSave"
,
""
,
buffer
,
sizeof
(
buffer
)
);
if
(
buffer
[
0
])
period
=
atoi
(
buffer
);
all
=
!
PROFILE_GetWineIniBool
(
registryW
,
SaveOnlyUpdatedKeysW
,
1
);
PROFILE_GetWineIniString
(
registryW
,
PeriodicSaveW
,
empty_strW
,
buffer
,
20
);
if
(
buffer
[
0
])
period
=
(
int
)
strtolW
(
buffer
,
NULL
,
10
);
/* set saving level (0 for saving everything, 1 for saving only modified keys) */
_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_LOCAL_MACHINE
,
"/"
SAVE_LOCAL_REGBRANCH_LOCAL_MACHINE
);
...
...
@@ -1118,29 +1123,33 @@ static void _allocate_default_keys(void) {
/* return the type of native registry [Internal] */
static
int
_get_reg_type
(
void
)
{
char
windir
[
MAX_PATHNAME_LEN
];
char
tmp
[
MAX_PATHNAME_LEN
];
WCHAR
windir
[
MAX_PATHNAME_LEN
];
WCHAR
tmp
[
MAX_PATHNAME_LEN
];
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
};
GetWindowsDirectory
A
(
windir
,
MAX_PATHNAME_LEN
);
GetWindowsDirectory
W
(
windir
,
MAX_PATHNAME_LEN
);
/* test %windir%/system32/config/system --> winnt */
strcpy
(
tmp
,
windir
);
str
ncat
(
tmp
,
"
\\
system32
\\
config
\\
system"
,
MAX_PATHNAME_LEN
-
strlen
(
tmp
)
-
1
);
if
(
GetFileAttributes
A
(
tmp
)
!=
(
DWORD
)
-
1
)
{
strcpy
W
(
tmp
,
windir
);
str
catW
(
tmp
,
nt_reg_pathW
);
if
(
GetFileAttributes
W
(
tmp
)
!=
(
DWORD
)
-
1
)
ret
=
REG_WINNT
;
}
else
{
/* test %windir%/system.dat --> win95 */
strcpy
(
tmp
,
windir
);
str
ncat
(
tmp
,
"
\\
system.dat"
,
MAX_PATHNAME_LEN
-
strlen
(
tmp
)
-
1
);
if
(
GetFileAttributes
A
(
tmp
)
!=
(
DWORD
)
-
1
)
{
strcpy
W
(
tmp
,
windir
);
str
catW
(
tmp
,
win9x_reg_pathW
);
if
(
GetFileAttributes
W
(
tmp
)
!=
(
DWORD
)
-
1
)
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
(
"'Profile=<profiledirectory>' or disable loading of Windows
\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] */
static
LPSTR
_convert_win95_registry_to_wine_format
(
LPC
STR
fn
,
int
level
)
static
LPSTR
_convert_win95_registry_to_wine_format
(
LPC
WSTR
fn
,
int
level
)
{
int
fd
;
FILE
*
f
;
...
...
@@ -1278,7 +1287,8 @@ static LPSTR _convert_win95_registry_to_wine_format(LPCSTR fn,int level)
/* control signature */
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
;
}
...
...
@@ -1324,7 +1334,7 @@ static LPSTR _convert_win95_registry_to_wine_format(LPCSTR fn,int level)
error:
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
(
"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] */
static
LPSTR
_convert_winnt_registry_to_wine_format
(
LPC
STR
fn
,
int
level
)
static
LPSTR
_convert_winnt_registry_to_wine_format
(
LPC
WSTR
fn
,
int
level
)
{
FILE
*
f
;
void
*
base
;
...
...
@@ -1349,11 +1359,11 @@ static LPSTR _convert_winnt_registry_to_wine_format(LPCSTR fn,int level)
nt_hbin_sub
*
hbin_sub
;
nt_nk
*
nk
;
TRACE
(
"%s
\n
"
,
fn
);
TRACE
(
"%s
\n
"
,
debugstr_w
(
fn
)
);
hFile
=
CreateFile
A
(
fn
,
GENERIC_READ
,
FILE_SHARE_READ
,
NULL
,
OPEN_EXISTING
,
0
,
0
);
hFile
=
CreateFile
W
(
fn
,
GENERIC_READ
,
FILE_SHARE_READ
,
NULL
,
OPEN_EXISTING
,
0
,
0
);
if
(
hFile
==
INVALID_HANDLE_VALUE
)
return
NULL
;
hMapping
=
CreateFileMapping
A
(
hFile
,
NULL
,
PAGE_READONLY
|
SEC_COMMIT
,
0
,
0
,
NULL
);
hMapping
=
CreateFileMapping
W
(
hFile
,
NULL
,
PAGE_READONLY
|
SEC_COMMIT
,
0
,
0
,
NULL
);
if
(
!
hMapping
)
goto
error1
;
base
=
MapViewOfFile
(
hMapping
,
FILE_MAP_READ
,
0
,
0
,
0
);
CloseHandle
(
hMapping
);
...
...
@@ -1361,7 +1371,8 @@ static LPSTR _convert_winnt_registry_to_wine_format(LPCSTR fn,int level)
/* control signature */
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
;
}
...
...
@@ -1402,7 +1413,7 @@ error1:
}
/* convert native registry to wine format and load it via server call [Internal] */
static
void
_convert_and_load_native_registry
(
LPC
STR
fn
,
HKEY
hkey
,
int
reg_type
,
int
level
)
static
void
_convert_and_load_native_registry
(
LPC
WSTR
fn
,
HKEY
hkey
,
int
reg_type
,
int
level
)
{
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
)
{
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
);
}
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
);
}
...
...
@@ -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
)
{
int
reg_type
;
char
windir
[
MAX_PATHNAME_LEN
];
char
path
[
MAX_PATHNAME_LEN
];
WCHAR
windir
[
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
};
GetWindowsDirectory
A
(
windir
,
MAX_PATHNAME_LEN
);
GetWindowsDirectory
W
(
windir
,
MAX_PATHNAME_LEN
);
reg_type
=
_get_reg_type
();
switch
(
reg_type
)
{
case
REG_WINNT
:
{
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 */
if
(
PROFILE_GetWineIniString
(
"Wine"
,
"Profile"
,
""
,
path
,
MAX_PATHNAME_LEN
))
{
strcat
(
path
,
"
\\
ntuser.dat"
);
if
(
PROFILE_GetWineIniString
(
WineW
,
ProfileW
,
empty_strW
,
path
,
MAX_PATHNAME_LEN
))
{
strcat
W
(
path
,
ntuser_datW
);
_convert_and_load_native_registry
(
path
,
HKEY_CURRENT_USER
,
REG_WINNT
,
1
);
}
/* default user.dat */
if
(
hkey_users_default
)
{
strcpy
(
path
,
windir
);
strcat
(
path
,
"
\\
system32
\\
config
\\
default"
);
strcpy
W
(
path
,
windir
);
strcat
W
(
path
,
defaultW
);
_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
))
{
strcpy
(
path
,
windir
);
strcat
(
path
,
"
\\
system32
\\
config
\\
system"
);
strcpy
W
(
path
,
windir
);
strcat
W
(
path
,
systemW
);
_convert_and_load_native_registry
(
path
,
hkey
,
REG_WINNT
,
1
);
RegCloseKey
(
hkey
);
}
if
(
!
RegCreateKeyA
(
HKEY_LOCAL_MACHINE
,
"SOFTWARE"
,
&
hkey
))
{
strcpy
(
path
,
windir
);
strcat
(
path
,
"
\\
system32
\\
config
\\
software"
);
strcpy
W
(
path
,
windir
);
strcat
W
(
path
,
softwareW
);
_convert_and_load_native_registry
(
path
,
hkey
,
REG_WINNT
,
1
);
RegCloseKey
(
hkey
);
}
strcpy
(
path
,
windir
);
strcat
(
path
,
"
\\
system32
\\
config
\\
sam"
);
strcpy
W
(
path
,
windir
);
strcat
W
(
path
,
samW
);
_convert_and_load_native_registry
(
path
,
HKEY_LOCAL_MACHINE
,
REG_WINNT
,
0
);
strcpy
(
path
,
windir
);
strcat
(
path
,
"
\\
system32
\\
config
\\
security"
);
strcpy
W
(
path
,
windir
);
strcat
W
(
path
,
securityW
);
_convert_and_load_native_registry
(
path
,
HKEY_LOCAL_MACHINE
,
REG_WINNT
,
0
);
/* 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
:
_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
};
_convert_and_load_native_registry
(
system_1stW
,
HKEY_LOCAL_MACHINE
,
REG_WIN95
,
0
);
strcpy
(
path
,
windir
);
strcat
(
path
,
"
\\
system.dat"
);
strcpy
W
(
path
,
windir
);
strcat
W
(
path
,
system_datW
);
_convert_and_load_native_registry
(
path
,
HKEY_LOCAL_MACHINE
,
REG_WIN95
,
0
);
strcpy
(
path
,
windir
);
strcat
(
path
,
"
\\
classes.dat"
);
strcpy
W
(
path
,
windir
);
strcat
W
(
path
,
classes_datW
);
_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 */
str
ncat
(
path
,
"
\\
user.dat"
,
MAX_PATHNAME_LEN
-
strlen
(
path
)
-
1
);
str
catW
(
path
,
user_datW
);
_convert_and_load_native_registry
(
path
,
HKEY_CURRENT_USER
,
REG_WIN95
,
1
);
/* default user.dat */
if
(
hkey_users_default
)
{
strcpy
(
path
,
windir
);
strcat
(
path
,
"
\\
user.dat"
);
strcpy
W
(
path
,
windir
);
strcat
W
(
path
,
user_datW
);
_convert_and_load_native_registry
(
path
,
hkey_users_default
,
REG_WIN95
,
1
);
}
}
else
{
strcpy
(
path
,
windir
);
strcat
(
path
,
"
\\
user.dat"
);
strcpy
W
(
path
,
windir
);
strcat
W
(
path
,
user_datW
);
_convert_and_load_native_registry
(
path
,
HKEY_CURRENT_USER
,
REG_WIN95
,
1
);
}
break
;
}
case
REG_WIN31
:
/* 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
)
{
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
"
);
...
...
@@ -1585,70 +1617,21 @@ void SHELL_LoadRegistry( void )
_allocate_default_keys
();
_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
);
if
(
PROFILE_GetWineIniBool
(
"Registry"
,
"LoadGlobalRegistryFiles"
,
1
))
if
(
PROFILE_GetWineIniBool
(
RegistryW
,
load_global_reg_filesW
,
1
))
_load_global_registry
();
_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
);
_init_registry_saving
(
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
* some programs. Do not remove those cases. -MM
*/
...
...
msdos/dosconf.c
View file @
d75aed2c
...
...
@@ -435,17 +435,19 @@ static void DOSCONF_Parse(char *menuname)
int
DOSCONF_ReadConfig
(
void
)
{
char
buffer
[
256
];
WCHAR
filename
[
MAX_PATH
];
DOS_FULL_NAME
fullname
;
char
*
filename
,
*
menuname
;
WCHAR
*
p
;
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
)
);
if
(
!
(
filename
=
strtok
(
buffer
,
","
)))
return
ret
;
menuname
=
strtok
(
NULL
,
","
)
;
PROFILE_GetWineIniString
(
wineW
,
config_sysW
,
empty_strW
,
filename
,
MAX_PATH
);
if
(
(
p
=
strchrW
(
filename
,
','
)))
*
p
=
0
;
if
(
!
filename
[
0
])
return
ret
;
DOSFS_GetFullName
(
filename
,
FALSE
,
&
fullname
);
if
(
menuname
)
menu_default
=
strdup
(
menuname
);
if
((
cfg_fd
=
fopen
(
fullname
.
long_name
,
"r"
)))
{
DOSCONF_Parse
(
NULL
);
...
...
@@ -453,10 +455,9 @@ int DOSCONF_ReadConfig(void)
}
else
{
MESSAGE
(
"Couldn't open config.sys file given as
\"
%s
\"
in"
\
" wine.conf or .winerc, section [wine] !
\n
"
,
filename
);
MESSAGE
(
"Couldn't open config.sys file given as
%s
in"
\
" wine.conf or .winerc, section [wine] !
\n
"
,
debugstr_w
(
filename
)
);
ret
=
0
;
}
if
(
menu_default
)
free
(
menu_default
);
return
ret
;
}
msdos/int11.c
View file @
d75aed2c
...
...
@@ -28,6 +28,7 @@
#include "miscemu.h"
#include "msdos.h"
#include "file.h"
#include "wine/unicode.h"
#include "wine/debug.h"
/**********************************************************************
...
...
@@ -74,16 +75,21 @@ void WINAPI INT_Int11Handler( CONTEXT86 *context )
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
)
;
PROFILE_GetWineIniString
(
"serialports"
,
name
,
"*"
,
temp
,
sizeof
temp
);
if
(
strcmp
(
temp
,
"*"
))
comW
[
3
]
=
'0'
+
x
;
PROFILE_GetWineIniString
(
serialportsW
,
comW
,
asteriskW
,
temp
,
16
);
if
(
strcmp
W
(
temp
,
asteriskW
))
serialports
++
;
sprintf
(
name
,
"LPT%d"
,
x
+
1
)
;
PROFILE_GetWineIniString
(
"parallelports"
,
name
,
"*"
,
temp
,
sizeof
temp
);
if
(
strcmp
(
temp
,
"*"
))
lptW
[
3
]
=
'0'
+
x
;
PROFILE_GetWineIniString
(
parallelportsW
,
lptW
,
asteriskW
,
temp
,
16
);
if
(
strcmp
W
(
temp
,
asteriskW
))
parallelports
++
;
}
if
(
serialports
>
7
)
/* 3 bits -- maximum value = 7 */
...
...
msdos/int21.c
View file @
d75aed2c
...
...
@@ -57,6 +57,7 @@
#include "msdos.h"
#include "miscemu.h"
#include "task.h"
#include "wine/unicode.h"
#include "wine/debug.h"
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
);
char
*
fcb
=
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 */
TRACE
(
"filename: '%s'
\n
"
,
filename
);
buffer
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlen
(
filename
)
+
1
);
s
=
filename
;
d
=
buffer
;
len
=
0
;
while
(
*
s
)
{
if
((
*
s
!=
' '
)
&&
(
*
s
!=
'\r'
)
&&
(
*
s
!=
'\n'
))
*
d
++
=
*
s
++
;
{
s
++
;
len
++
;
}
else
break
;
}
*
d
=
'\0'
;
DOSFS_ToDosFCBFormat
(
buffer
,
fcb
+
1
);
buffer_len
=
MultiByteToWideChar
(
CP_OEMCP
,
0
,
filename
,
len
,
NULL
,
0
);
buffer
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
buffer_len
+
1
)
*
sizeof
(
WCHAR
));
len
=
MultiByteToWideChar
(
CP_OEMCP
,
0
,
filename
,
len
,
buffer
,
buffer_len
);
buffer
[
len
]
=
0
;
DOSFS_ToDosFCBFormat
(
buffer
,
fcbW
);
HeapFree
(
GetProcessHeap
(),
0
,
buffer
);
WideCharToMultiByte
(
CP_OEMCP
,
0
,
fcbW
,
12
,
fcb
+
1
,
12
,
NULL
,
NULL
);
*
fcb
=
0
;
TRACE
(
"FCB: '%s'
\n
"
,
((
CHAR
*
)
fcb
+
1
));
HeapFree
(
GetProcessHeap
(),
0
,
buffer
);
TRACE
(
"FCB: '%s'
\n
"
,
fcb
+
1
);
AL_reg
(
context
)
=
((
strchr
(
filename
,
'*'
))
||
(
strchr
(
filename
,
'$'
)))
!=
0
;
...
...
@@ -618,6 +626,7 @@ static BOOL INT21_ChangeDir( CONTEXT86 *context )
{
int
drive
;
char
*
dirname
=
CTX_SEG_OFF_TO_LIN
(
context
,
context
->
SegDs
,
context
->
Edx
);
WCHAR
dirnameW
[
MAX_PATH
];
TRACE
(
"changedir %s
\n
"
,
dirname
);
if
(
dirname
[
0
]
&&
(
dirname
[
1
]
==
':'
))
...
...
@@ -626,7 +635,8 @@ static BOOL INT21_ChangeDir( CONTEXT86 *context )
dirname
+=
2
;
}
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
;
DOS_FULL_NAME
full_name
;
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
);
MultiByteToWideChar
(
CP_OEMCP
,
0
,
path
,
-
1
,
pathW
,
MAX_PATH
);
dta
->
unixPath
=
NULL
;
if
(
!
DOSFS_GetFullName
(
path
,
FALSE
,
&
full_name
))
if
(
!
DOSFS_GetFullName
(
path
W
,
FALSE
,
&
full_name
))
{
AX_reg
(
context
)
=
GetLastError
();
SET_CFLAG
(
context
);
...
...
@@ -650,10 +664,12 @@ static int INT21_FindFirst( CONTEXT86 *context )
p
=
strrchr
(
dta
->
unixPath
,
'/'
);
*
p
=
'\0'
;
MultiByteToWideChar
(
CP_OEMCP
,
0
,
p
+
1
,
-
1
,
pathW
,
MAX_PATH
);
/* Note: terminating NULL in dta->mask overwrites dta->search_attr
* (doesn't matter as it is set below anyway)
*/
if
(
!
DOSFS_ToDosFCBFormat
(
p
+
1
,
dta
->
mask
))
if
(
!
DOSFS_ToDosFCBFormat
(
p
athW
,
maskW
))
{
HeapFree
(
GetProcessHeap
(),
0
,
dta
->
unixPath
);
dta
->
unixPath
=
NULL
;
...
...
@@ -662,6 +678,7 @@ static int INT21_FindFirst( CONTEXT86 *context )
SET_CFLAG
(
context
);
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'
:
DRIVE_GetCurrentDrive
();
dta
->
count
=
0
;
...
...
@@ -743,7 +760,8 @@ static BOOL INT21_GetCurrentDirectory( CONTEXT86 *context )
SetLastError
(
ERROR_INVALID_DRIVE
);
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 */
return
TRUE
;
}
...
...
@@ -1586,8 +1604,9 @@ void WINAPI DOS3Call( CONTEXT86 *context )
break
;
case
0x02
:{
const
DOS_DEVICE
*
dev
;
static
const
WCHAR
scsimgrW
[]
=
{
'S'
,
'C'
,
'S'
,
'I'
,
'M'
,
'G'
,
'R'
,
'$'
,
0
};
if
((
dev
=
DOSFS_GetDeviceByHandle
(
DosFileHandleToWin32Handle
(
BX_reg
(
context
))
))
&&
!
strc
asecmp
(
dev
->
name
,
"SCSIMGR$"
))
!
strc
mpiW
(
dev
->
name
,
scsimgrW
))
{
ASPI_DOS_HandleInt
(
context
);
}
...
...
msdos/ioports.c
View file @
d75aed2c
...
...
@@ -36,6 +36,7 @@
# include <unistd.h>
#endif
#include "windef.h"
#include "winnls.h"
#include "callback.h"
#include "file.h"
#include "miscemu.h"
...
...
@@ -249,17 +250,22 @@ static inline void outl( DWORD value, WORD port )
static
void
IO_port_init
(
void
)
{
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
;
/* Can we do that? */
if
(
!
iopl
(
3
))
{
iopl
(
0
);
PROFILE_GetWineIniString
(
"ports"
,
"read"
,
"*"
,
temp
,
sizeof
(
temp
)
);
PROFILE_GetWineIniString
(
portsW
,
readW
,
asteriskW
,
tempW
,
1024
);
WideCharToMultiByte
(
CP_ACP
,
0
,
tempW
,
-
1
,
temp
,
1024
,
NULL
,
NULL
);
do_IO_port_init_read_or_write
(
temp
,
IO_READ
);
PROFILE_GetWineIniString
(
"ports"
,
"write"
,
"*"
,
temp
,
sizeof
(
temp
)
);
PROFILE_GetWineIniString
(
portsW
,
writeW
,
asteriskW
,
tempW
,
1024
);
WideCharToMultiByte
(
CP_ACP
,
0
,
tempW
,
-
1
,
temp
,
1024
,
NULL
,
NULL
);
do_IO_port_init_read_or_write
(
temp
,
IO_WRITE
);
}
IO_FixCMOSCheckSum
();
...
...
scheduler/process.c
View file @
d75aed2c
...
...
@@ -650,9 +650,12 @@ void PROCESS_InitWine( int argc, char *argv[], LPSTR win16_exe_name, HANDLE *win
{
DOS_FULL_NAME
full_name
;
const
char
*
name
=
main_exe_name
;
UNICODE_STRING
nameW
;
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
);
main_exe_file
=
0
;
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
(
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
;
RtlFreeUnicodeString
(
&
cur_dirW
);
}
else
{
char
buf
[
MAX_PATH
];
if
(
GetCurrentDirectory
A
(
sizeof
(
buf
),
buf
))
WCHAR
buf
[
MAX_PATH
];
if
(
GetCurrentDirectory
W
(
MAX_PATH
,
buf
))
{
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 */
case
BINARY_UNIX_EXE
:
{
/* unknown file, try as unix executable */
UNICODE_STRING
nameW
;
DOS_FULL_NAME
full_name
;
const
char
*
unixfilename
=
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
);
}
break
;
...
...
win32/device.c
View file @
d75aed2c
...
...
@@ -344,9 +344,16 @@ LPCSTR VMM_Service_Name[N_VMM_SERVICE] =
HANDLE
DEVICE_Open
(
LPC
STR
filename
,
DWORD
access
,
LPSECURITY_ATTRIBUTES
sa
)
HANDLE
DEVICE_Open
(
LPC
WSTR
filenameW
,
DWORD
access
,
LPSECURITY_ATTRIBUTES
sa
)
{
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
++
)
if
(
!
strncasecmp
(
info
->
name
,
filename
,
strlen
(
info
->
name
)
))
...
...
@@ -1563,4 +1570,3 @@ static BOOL DeviceIo_HASP(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInB
return
retv
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment