Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
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-winehq
Commits
18a960bb
Commit
18a960bb
authored
Mar 27, 2020
by
Zebediah Figura
Committed by
Alexandre Julliard
Apr 06, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Implement NtQueryVolumeInformationFile(FileFsAttributeInformation).
Signed-off-by:
Zebediah Figura
<
zfigura@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
54f93b9b
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
204 additions
and
14 deletions
+204
-14
file.c
dlls/ntdll/file.c
+204
-14
No files found.
dlls/ntdll/file.c
View file @
18a960bb
...
...
@@ -107,6 +107,8 @@
#include "winioctl.h"
#include "ddk/ntddk.h"
#include "ddk/ntddser.h"
#define WINE_MOUNTMGR_EXTENSIONS
#include "ddk/mountmgr.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
ntdll
);
WINE_DECLARE_DEBUG_CHANNEL
(
winediag
);
...
...
@@ -119,8 +121,6 @@ mode_t FILE_umask = 0;
#define FILE_WRITE_TO_END_OF_FILE ((LONGLONG)-1)
#define FILE_USE_FILE_POINTER_POSITION ((LONGLONG)-2)
static
const
WCHAR
ntfsW
[]
=
{
'N'
,
'T'
,
'F'
,
'S'
};
/* fetch the attributes of a file */
static
inline
ULONG
get_file_attributes
(
const
struct
stat
*
st
)
{
...
...
@@ -3120,6 +3120,124 @@ static NTSTATUS get_device_info( int fd, FILE_FS_DEVICE_INFORMATION *info )
return
STATUS_SUCCESS
;
}
/* Find a DOS device which can act as the root of "path".
* Similar to find_drive_root(), but returns -1 instead of crossing volumes. */
static
int
find_dos_device
(
const
char
*
path
)
{
int
len
=
strlen
(
path
);
int
drive
;
char
*
buffer
;
struct
stat
st
;
struct
drive_info
info
[
MAX_DOS_DRIVES
];
dev_t
dev_id
;
if
(
!
DIR_get_drives_info
(
info
))
return
-
1
;
if
(
stat
(
path
,
&
st
)
<
0
)
return
-
1
;
dev_id
=
st
.
st_dev
;
/* strip off trailing slashes */
while
(
len
>
1
&&
path
[
len
-
1
]
==
'/'
)
len
--
;
/* make a copy of the path */
if
(
!
(
buffer
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
len
+
1
)))
return
-
1
;
memcpy
(
buffer
,
path
,
len
);
buffer
[
len
]
=
0
;
for
(;;)
{
if
(
!
stat
(
buffer
,
&
st
)
&&
S_ISDIR
(
st
.
st_mode
))
{
if
(
st
.
st_dev
!=
dev_id
)
break
;
for
(
drive
=
0
;
drive
<
MAX_DOS_DRIVES
;
drive
++
)
{
if
((
info
[
drive
].
dev
==
st
.
st_dev
)
&&
(
info
[
drive
].
ino
==
st
.
st_ino
))
{
if
(
len
==
1
)
len
=
0
;
/* preserve root slash in returned path */
TRACE
(
"%s -> drive %c:, root=%s, name=%s
\n
"
,
debugstr_a
(
path
),
'A'
+
drive
,
debugstr_a
(
buffer
),
debugstr_a
(
path
+
len
));
RtlFreeHeap
(
GetProcessHeap
(),
0
,
buffer
);
return
drive
;
}
}
}
if
(
len
<=
1
)
break
;
/* reached root */
while
(
path
[
len
-
1
]
!=
'/'
)
len
--
;
while
(
path
[
len
-
1
]
==
'/'
)
len
--
;
buffer
[
len
]
=
0
;
}
RtlFreeHeap
(
GetProcessHeap
(),
0
,
buffer
);
return
-
1
;
}
static
struct
mountmgr_unix_drive
*
get_mountmgr_fs_info
(
HANDLE
handle
,
int
fd
)
{
struct
mountmgr_unix_drive
*
drive
;
OBJECT_ATTRIBUTES
attr
;
UNICODE_STRING
string
;
ANSI_STRING
unix_name
;
IO_STATUS_BLOCK
io
;
HANDLE
mountmgr
;
NTSTATUS
status
;
int
letter
;
if
(
server_get_unix_name
(
handle
,
&
unix_name
))
return
NULL
;
letter
=
find_dos_device
(
unix_name
.
Buffer
);
RtlFreeAnsiString
(
&
unix_name
);
if
(
!
(
drive
=
RtlAllocateHeap
(
GetProcessHeap
(),
0
,
1024
)))
return
NULL
;
if
(
letter
==
-
1
)
{
struct
stat
st
;
if
(
fstat
(
fd
,
&
st
)
==
-
1
)
{
RtlFreeHeap
(
GetProcessHeap
(),
0
,
drive
);
return
NULL
;
}
drive
->
unix_dev
=
st
.
st_dev
;
drive
->
letter
=
0
;
}
else
drive
->
letter
=
'a'
+
letter
;
RtlInitUnicodeString
(
&
string
,
MOUNTMGR_DEVICE_NAME
);
InitializeObjectAttributes
(
&
attr
,
&
string
,
0
,
NULL
,
NULL
);
if
(
NtOpenFile
(
&
mountmgr
,
GENERIC_READ
|
SYNCHRONIZE
,
&
attr
,
&
io
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
FILE_SYNCHRONOUS_IO_NONALERT
))
return
NULL
;
status
=
NtDeviceIoControlFile
(
mountmgr
,
NULL
,
NULL
,
NULL
,
&
io
,
IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE
,
drive
,
sizeof
(
*
drive
),
drive
,
1024
);
if
(
status
==
STATUS_BUFFER_OVERFLOW
)
{
if
(
!
(
drive
=
RtlReAllocateHeap
(
GetProcessHeap
(),
0
,
drive
,
drive
->
size
)))
{
RtlFreeHeap
(
GetProcessHeap
(),
0
,
drive
);
NtClose
(
mountmgr
);
return
NULL
;
}
status
=
NtDeviceIoControlFile
(
mountmgr
,
NULL
,
NULL
,
NULL
,
&
io
,
IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE
,
drive
,
sizeof
(
*
drive
),
drive
,
drive
->
size
);
}
NtClose
(
mountmgr
);
if
(
status
)
{
WARN
(
"failed to retrieve filesystem type from mountmgr, status %#x
\n
"
,
status
);
RtlFreeHeap
(
GetProcessHeap
(),
0
,
drive
);
return
NULL
;
}
return
drive
;
}
/******************************************************************************
* NtQueryVolumeInformationFile [NTDLL.@]
...
...
@@ -3240,24 +3358,96 @@ NTSTATUS WINAPI NtQueryVolumeInformationFile( HANDLE handle, PIO_STATUS_BLOCK io
}
break
;
case
FileFsAttributeInformation
:
if
(
length
<
offsetof
(
FILE_FS_ATTRIBUTE_INFORMATION
,
FileSystemName
[
ARRAY_SIZE
(
ntfsW
)]
))
io
->
u
.
Status
=
STATUS_BUFFER_TOO_SMALL
;
{
static
const
WCHAR
fatW
[]
=
{
'F'
,
'A'
,
'T'
};
static
const
WCHAR
fat32W
[]
=
{
'F'
,
'A'
,
'T'
,
'3'
,
'2'
};
static
const
WCHAR
ntfsW
[]
=
{
'N'
,
'T'
,
'F'
,
'S'
};
static
const
WCHAR
cdfsW
[]
=
{
'C'
,
'D'
,
'F'
,
'S'
};
static
const
WCHAR
udfW
[]
=
{
'U'
,
'D'
,
'F'
};
FILE_FS_ATTRIBUTE_INFORMATION
*
info
=
buffer
;
struct
mountmgr_unix_drive
*
drive
;
enum
mountmgr_fs_type
fs_type
=
MOUNTMGR_FS_TYPE_NTFS
;
if
(
length
<
sizeof
(
FILE_FS_ATTRIBUTE_INFORMATION
))
{
io
->
u
.
Status
=
STATUS_INFO_LENGTH_MISMATCH
;
break
;
}
if
((
drive
=
get_mountmgr_fs_info
(
handle
,
fd
)))
{
fs_type
=
drive
->
fs_type
;
RtlFreeHeap
(
GetProcessHeap
(),
0
,
drive
);
}
else
{
FILE_FS_ATTRIBUTE_INFORMATION
*
info
=
buffer
;
struct
statfs
stfs
;
FIXME
(
"%p: faking attribute info
\n
"
,
handle
);
info
->
FileSystemAttributes
=
FILE_SUPPORTS_ENCRYPTION
|
FILE_FILE_COMPRESSION
|
FILE_PERSISTENT_ACLS
|
FILE_UNICODE_ON_DISK
|
FILE_CASE_PRESERVED_NAMES
|
FILE_CASE_SENSITIVE_SEARCH
;
info
->
MaximumComponentNameLength
=
MAXIMUM_FILENAME_LENGTH
-
1
;
info
->
FileSystemNameLength
=
sizeof
(
ntfsW
);
memcpy
(
info
->
FileSystemName
,
ntfsW
,
sizeof
(
ntfsW
));
if
(
!
fstatfs
(
fd
,
&
stfs
))
{
#if defined(linux) && defined(HAVE_FSTATFS)
switch
(
stfs
.
f_type
)
{
case
0x9660
:
fs_type
=
MOUNTMGR_FS_TYPE_ISO9660
;
break
;
case
0x15013346
:
fs_type
=
MOUNTMGR_FS_TYPE_UDF
;
break
;
case
0x4d44
:
fs_type
=
MOUNTMGR_FS_TYPE_FAT32
;
break
;
}
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__)
if
(
!
strcmp
(
stfs
.
f_fstypename
,
"cd9660"
))
fs_type
=
MOUNTMGR_FS_TYPE_ISO9660
;
else
if
(
!
strcmp
(
stfs
.
f_fstypename
,
"udf"
))
fs_type
=
MOUNTMGR_FS_TYPE_UDF
;
else
if
(
!
strcmp
(
stfs
.
f_fstypename
,
"msdos"
))
fs_type
=
MOUNTMGR_FS_TYPE_FAT32
;
#endif
}
}
io
->
Information
=
sizeof
(
*
info
);
io
->
u
.
Status
=
STATUS_SUCCESS
;
switch
(
fs_type
)
{
case
MOUNTMGR_FS_TYPE_ISO9660
:
info
->
FileSystemAttributes
=
FILE_READ_ONLY_VOLUME
;
info
->
MaximumComponentNameLength
=
221
;
info
->
FileSystemNameLength
=
min
(
sizeof
(
cdfsW
),
length
-
offsetof
(
FILE_FS_ATTRIBUTE_INFORMATION
,
FileSystemName
)
);
memcpy
(
info
->
FileSystemName
,
cdfsW
,
info
->
FileSystemNameLength
);
break
;
case
MOUNTMGR_FS_TYPE_UDF
:
info
->
FileSystemAttributes
=
FILE_READ_ONLY_VOLUME
|
FILE_UNICODE_ON_DISK
|
FILE_CASE_SENSITIVE_SEARCH
;
info
->
MaximumComponentNameLength
=
255
;
info
->
FileSystemNameLength
=
min
(
sizeof
(
udfW
),
length
-
offsetof
(
FILE_FS_ATTRIBUTE_INFORMATION
,
FileSystemName
)
);
memcpy
(
info
->
FileSystemName
,
udfW
,
info
->
FileSystemNameLength
);
break
;
case
MOUNTMGR_FS_TYPE_FAT
:
info
->
FileSystemAttributes
=
FILE_CASE_PRESERVED_NAMES
;
/* FIXME */
info
->
MaximumComponentNameLength
=
255
;
info
->
FileSystemNameLength
=
min
(
sizeof
(
fatW
),
length
-
offsetof
(
FILE_FS_ATTRIBUTE_INFORMATION
,
FileSystemName
)
);
memcpy
(
info
->
FileSystemName
,
fatW
,
info
->
FileSystemNameLength
);
break
;
case
MOUNTMGR_FS_TYPE_FAT32
:
info
->
FileSystemAttributes
=
FILE_CASE_PRESERVED_NAMES
;
/* FIXME */
info
->
MaximumComponentNameLength
=
255
;
info
->
FileSystemNameLength
=
min
(
sizeof
(
fat32W
),
length
-
offsetof
(
FILE_FS_ATTRIBUTE_INFORMATION
,
FileSystemName
)
);
memcpy
(
info
->
FileSystemName
,
fat32W
,
info
->
FileSystemNameLength
);
break
;
default:
info
->
FileSystemAttributes
=
FILE_CASE_PRESERVED_NAMES
|
FILE_PERSISTENT_ACLS
;
info
->
MaximumComponentNameLength
=
255
;
info
->
FileSystemNameLength
=
min
(
sizeof
(
ntfsW
),
length
-
offsetof
(
FILE_FS_ATTRIBUTE_INFORMATION
,
FileSystemName
)
);
memcpy
(
info
->
FileSystemName
,
ntfsW
,
info
->
FileSystemNameLength
);
break
;
}
io
->
Information
=
offsetof
(
FILE_FS_ATTRIBUTE_INFORMATION
,
FileSystemName
)
+
info
->
FileSystemNameLength
;
io
->
u
.
Status
=
STATUS_SUCCESS
;
break
;
}
case
FileFsControlInformation
:
FIXME
(
"%p: control info not supported
\n
"
,
handle
);
break
;
...
...
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