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
73f4e239
Commit
73f4e239
authored
Sep 01, 2011
by
Alexandre Goujon
Committed by
Alexandre Julliard
Sep 06, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
kernel32: Add UDF support.
Based on Steven Wallace work.
parent
b0dfa932
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
144 additions
and
16 deletions
+144
-16
volume.c
dlls/kernel32/volume.c
+144
-16
No files found.
dlls/kernel32/volume.c
View file @
73f4e239
...
...
@@ -46,7 +46,8 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
volume
);
#define SUPERBLOCK_SIZE 2048
#define BLOCK_SIZE 2048
#define SUPERBLOCK_SIZE BLOCK_SIZE
#define SYMBOLIC_LINK_QUERY 0x0001
#define CDFRAMES_PERSEC 75
...
...
@@ -63,7 +64,8 @@ enum fs_type
FS_UNKNOWN
,
/* unknown file system */
FS_FAT1216
,
FS_FAT32
,
FS_ISO9660
FS_ISO9660
,
FS_UDF
/* For reference [E] = Ecma-167.pdf, [U] = udf260.pdf */
};
/* read a Unix symlink; returned buffer must be freed by caller */
...
...
@@ -387,30 +389,106 @@ static enum fs_type VOLUME_ReadFATSuperblock( HANDLE handle, BYTE *buff )
/***********************************************************************
* VOLUME_ReadCDBlock
*/
static
BOOL
VOLUME_ReadCDBlock
(
HANDLE
handle
,
BYTE
*
buff
,
INT
offs
)
{
DWORD
size
,
whence
=
offs
>=
0
?
FILE_BEGIN
:
FILE_END
;
if
(
SetFilePointer
(
handle
,
offs
,
NULL
,
whence
)
!=
offs
||
!
ReadFile
(
handle
,
buff
,
SUPERBLOCK_SIZE
,
&
size
,
NULL
)
||
size
!=
SUPERBLOCK_SIZE
)
return
FALSE
;
return
TRUE
;
}
/***********************************************************************
* VOLUME_ReadCDSuperblock
*/
static
enum
fs_type
VOLUME_ReadCDSuperblock
(
HANDLE
handle
,
BYTE
*
buff
)
{
DWORD
size
,
offs
=
VOLUME_FindCdRomDataBestVoldesc
(
handle
);
int
i
;
DWORD
offs
;
/* Check UDF first as UDF and ISO9660 structures can coexist on the same medium
* Starting from sector 16, we may find :
* - a CD-ROM Volume Descriptor Set (ISO9660) containing one or more Volume Descriptors
* - an Extented Area (UDF) -- [E] 2/8.3.1 and [U] 2.1.7
* There is no explicit end so read 16 sectors and then give up */
for
(
i
=
16
;
i
<
16
+
16
;
i
++
)
{
if
(
!
VOLUME_ReadCDBlock
(
handle
,
buff
,
i
*
BLOCK_SIZE
))
continue
;
/* We are supposed to check "BEA01", "NSR0x" and "TEA01" IDs + verify tag checksum
* but we assume the volume is well-formatted */
if
(
!
memcmp
(
&
buff
[
1
],
"BEA01"
,
5
))
return
FS_UDF
;
}
offs
=
VOLUME_FindCdRomDataBestVoldesc
(
handle
);
if
(
!
offs
)
return
FS_UNKNOWN
;
if
(
SetFilePointer
(
handle
,
offs
,
NULL
,
FILE_BEGIN
)
!=
offs
||
!
ReadFile
(
handle
,
buff
,
SUPERBLOCK_SIZE
,
&
size
,
NULL
)
||
size
!=
SUPERBLOCK_SIZE
)
if
(
!
VOLUME_ReadCDBlock
(
handle
,
buff
,
offs
))
return
FS_ERROR
;
/* check for
iso9660 present
*/
/* check for
the iso9660 identifier
*/
if
(
!
memcmp
(
&
buff
[
1
],
"CD001"
,
5
))
return
FS_ISO9660
;
return
FS_UNKNOWN
;
}
/**************************************************************************
* UDF_Find_PVD
* Find the Primary Volume Descriptor
*/
static
BOOL
UDF_Find_PVD
(
HANDLE
handle
,
BYTE
pvd
[]
)
{
int
i
;
DWORD
offset
;
INT
locations
[]
=
{
256
,
-
1
,
-
257
,
512
};
for
(
i
=
0
;
i
<
sizeof
(
locations
)
/
sizeof
(
locations
[
0
]);
i
++
)
{
if
(
!
VOLUME_ReadCDBlock
(
handle
,
pvd
,
locations
[
i
]
*
BLOCK_SIZE
))
return
FALSE
;
/* Tag Identifier of Anchor Volume Descriptor Pointer is 2 -- [E] 3/10.2.1 */
if
(
pvd
[
0
]
==
2
&&
pvd
[
1
]
==
0
)
{
/* Tag location (Uint32) at offset 12, little-endian */
offset
=
pvd
[
20
+
0
];
offset
|=
pvd
[
20
+
1
]
<<
8
;
offset
|=
pvd
[
20
+
2
]
<<
16
;
offset
|=
pvd
[
20
+
3
]
<<
24
;
offset
*=
BLOCK_SIZE
;
if
(
!
VOLUME_ReadCDBlock
(
handle
,
pvd
,
offset
))
return
FALSE
;
/* Check for the Primary Volume Descriptor Tag Id -- [E] 3/10.1.1 */
if
(
pvd
[
0
]
!=
1
||
pvd
[
1
]
!=
0
)
return
FALSE
;
/* 8 or 16 bits per character -- [U] 2.1.1 */
if
(
!
(
pvd
[
24
]
==
8
||
pvd
[
24
]
==
16
))
return
FALSE
;
return
TRUE
;
}
}
return
FALSE
;
}
/**************************************************************************
* VOLUME_GetSuperblockLabel
*/
static
void
VOLUME_GetSuperblockLabel
(
const
UNICODE_STRING
*
device
,
enum
fs_type
type
,
const
BYTE
*
superblock
,
WCHAR
*
label
,
DWORD
len
)
static
void
VOLUME_GetSuperblockLabel
(
const
UNICODE_STRING
*
device
,
HANDLE
handle
,
enum
fs_type
type
,
const
BYTE
*
superblock
,
WCHAR
*
label
,
DWORD
len
)
{
const
BYTE
*
label_ptr
=
NULL
;
DWORD
label_len
;
...
...
@@ -451,6 +529,34 @@ static void VOLUME_GetSuperblockLabel( const UNICODE_STRING *device, enum fs_typ
label_len
=
32
;
break
;
}
case
FS_UDF
:
{
BYTE
pvd
[
BLOCK_SIZE
];
if
(
!
UDF_Find_PVD
(
handle
,
pvd
))
{
label_len
=
0
;
break
;
}
/* [E] 3/10.1.4 and [U] 2.1.1 */
if
(
pvd
[
24
]
==
8
)
{
label_ptr
=
pvd
+
24
+
1
;
label_len
=
pvd
[
24
+
32
-
1
];
break
;
}
else
{
int
i
;
label_len
=
1
+
pvd
[
24
+
32
-
1
];
for
(
i
=
0
;
i
<
label_len
&&
i
<
len
;
i
+=
2
)
label
[
i
/
2
]
=
(
pvd
[
24
+
1
+
i
]
<<
8
)
|
pvd
[
24
+
1
+
i
+
1
];
label
[
label_len
]
=
0
;
return
;
}
}
}
if
(
label_len
)
RtlMultiByteToUnicodeN
(
label
,
(
len
-
1
)
*
sizeof
(
WCHAR
),
&
label_len
,
(
LPCSTR
)
label_ptr
,
label_len
);
...
...
@@ -463,8 +569,8 @@ static void VOLUME_GetSuperblockLabel( const UNICODE_STRING *device, enum fs_typ
/**************************************************************************
* VOLUME_GetSuperblockSerial
*/
static
DWORD
VOLUME_GetSuperblockSerial
(
const
UNICODE_STRING
*
device
,
enum
fs_type
typ
e
,
const
BYTE
*
superblock
)
static
DWORD
VOLUME_GetSuperblockSerial
(
const
UNICODE_STRING
*
device
,
HANDLE
handl
e
,
enum
fs_type
type
,
const
BYTE
*
superblock
)
{
switch
(
type
)
{
...
...
@@ -476,6 +582,17 @@ static DWORD VOLUME_GetSuperblockSerial( const UNICODE_STRING *device, enum fs_t
return
GETLONG
(
superblock
,
0x27
);
case
FS_FAT32
:
return
GETLONG
(
superblock
,
0x33
);
case
FS_UDF
:
{
BYTE
block
[
BLOCK_SIZE
];
if
(
!
VOLUME_ReadCDBlock
(
handle
,
block
,
257
*
BLOCK_SIZE
))
break
;
superblock
=
block
;
/* fallthrough */
}
case
FS_ISO9660
:
{
BYTE
sum
[
4
];
...
...
@@ -495,7 +612,7 @@ static DWORD VOLUME_GetSuperblockSerial( const UNICODE_STRING *device, enum fs_t
* Me$$ysoft chose to reverse the serial number in NT4/W2K.
* It's true and nobody will ever be able to change it.
*/
if
(
GetVersion
()
&
0x80000000
)
if
(
GetVersion
()
&
0x80000000
||
type
==
FS_UDF
)
return
(
sum
[
3
]
<<
24
)
|
(
sum
[
2
]
<<
16
)
|
(
sum
[
1
]
<<
8
)
|
sum
[
0
];
else
return
(
sum
[
0
]
<<
24
)
|
(
sum
[
1
]
<<
16
)
|
(
sum
[
2
]
<<
8
)
|
sum
[
3
];
...
...
@@ -546,6 +663,7 @@ BOOL WINAPI GetVolumeInformationW( LPCWSTR root, LPWSTR label, DWORD label_len,
static
const
WCHAR
fat32W
[]
=
{
'F'
,
'A'
,
'T'
,
'3'
,
'2'
,
0
};
static
const
WCHAR
ntfsW
[]
=
{
'N'
,
'T'
,
'F'
,
'S'
,
0
};
static
const
WCHAR
cdfsW
[]
=
{
'C'
,
'D'
,
'F'
,
'S'
,
0
};
static
const
WCHAR
udfW
[]
=
{
'U'
,
'D'
,
'F'
,
0
};
static
const
WCHAR
default_rootW
[]
=
{
'\\'
,
0
};
HANDLE
handle
;
...
...
@@ -618,12 +736,16 @@ BOOL WINAPI GetVolumeInformationW( LPCWSTR root, LPWSTR label, DWORD label_len,
type
=
VOLUME_ReadFATSuperblock
(
handle
,
superblock
);
if
(
type
==
FS_UNKNOWN
)
type
=
VOLUME_ReadCDSuperblock
(
handle
,
superblock
);
}
CloseHandle
(
handle
);
TRACE
(
"%s: found fs type %d
\n
"
,
debugstr_w
(
nt_name
.
Buffer
),
type
);
if
(
type
==
FS_ERROR
)
goto
done
;
if
(
type
==
FS_ERROR
)
{
CloseHandle
(
handle
);
goto
done
;
}
if
(
label
&&
label_len
)
VOLUME_GetSuperblockLabel
(
&
nt_name
,
type
,
superblock
,
label
,
label_len
);
if
(
serial
)
*
serial
=
VOLUME_GetSuperblockSerial
(
&
nt_name
,
type
,
superblock
);
if
(
label
&&
label_len
)
VOLUME_GetSuperblockLabel
(
&
nt_name
,
handle
,
type
,
superblock
,
label
,
label_len
);
if
(
serial
)
*
serial
=
VOLUME_GetSuperblockSerial
(
&
nt_name
,
handle
,
type
,
superblock
);
CloseHandle
(
handle
);
goto
fill_fs_info
;
}
else
TRACE
(
"cannot open device %s: %x
\n
"
,
debugstr_w
(
nt_name
.
Buffer
),
status
);
...
...
@@ -657,6 +779,12 @@ fill_fs_info: /* now fill in the information that depends on the file system ty
if
(
filename_len
)
*
filename_len
=
221
;
if
(
flags
)
*
flags
=
FILE_READ_ONLY_VOLUME
;
break
;
case
FS_UDF
:
if
(
fsname
)
lstrcpynW
(
fsname
,
udfW
,
fsname_len
);
if
(
filename_len
)
*
filename_len
=
255
;
if
(
flags
)
*
flags
=
FILE_READ_ONLY_VOLUME
|
FILE_UNICODE_ON_DISK
|
FILE_CASE_SENSITIVE_SEARCH
;
break
;
case
FS_FAT1216
:
if
(
fsname
)
lstrcpynW
(
fsname
,
fatW
,
fsname_len
);
case
FS_FAT32
:
...
...
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