diff --git a/dlls/kernel32/volume.c b/dlls/kernel32/volume.c index 25affc3f46f..4a2a7b5d323 100644 --- a/dlls/kernel32/volume.c +++ b/dlls/kernel32/volume.c @@ -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 */ @@ -386,31 +388,107 @@ 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