- fixed a gross bug in SetCurrentDirectoryA (where changing to a new

non-existent directory would leave the new drive enabled upon aborting
  (fixes CuteFTP install and should fix MANY apps)
  This has probably been caused by myself. *brownpaperbag*
- added GetVolumeInformation serial number bug-for-bug compatibility
- corrected Unicode labels (better CD-ROM handling in general)
- moved CD-ROM label detection code to misc/cdrom.c
- possible to use loopback mounted ISO9660 files
- init some uninitialised drive fields
- remove some unnecessary header includes
This commit is contained in:
Andreas Mohr 2000-07-25 20:59:59 +00:00 committed by Alexandre Julliard
parent f2355e0f15
commit 3084b58606
4 changed files with 163 additions and 76 deletions

View File

@ -239,6 +239,7 @@ int DRIVE_Init(void)
strcpy( DOSDrives[2].label_conf, "Drive C " );
DOSDrives[2].serial_conf = 12345678;
DOSDrives[2].type = TYPE_HD;
DOSDrives[2].device = NULL;
DOSDrives[2].flags = 0;
DRIVE_CurDrive = 2;
}
@ -456,9 +457,7 @@ int DRIVE_ReadSuperblock (int drive, char * buff)
offs = 0;
break;
case TYPE_CDROM:
/* FIXME: Maybe we should search for the first data track on the CD,
not just assume that it is the first track */
offs = (off_t)2048*(16+0);
offs = CDROM_Data_FindBestVoldesc(fd);
break;
default:
offs = 0;
@ -473,7 +472,7 @@ int DRIVE_ReadSuperblock (int drive, char * buff)
case TYPE_FLOPPY:
case TYPE_HD:
if ((buff[0x26]!=0x29) || /* Check for FAT present */
/* FIXME: do really all Fat have their name beginning with
/* FIXME: do really all FAT have their name beginning with
"FAT" ? (At least FAT12, FAT16 and FAT32 have :) */
memcmp( buff+0x36,"FAT",3))
{
@ -544,41 +543,20 @@ const char * DRIVE_GetLabel( int drive )
if (!DRIVE_IsValid( drive )) return NULL;
if (DRIVE_GetType(drive) == TYPE_CDROM)
{
WINE_CDAUDIO wcda;
if (!(CDROM_Open(&wcda, drive)))
{
int media = CDROM_GetMediaType(&wcda);
if (media == CDS_AUDIO)
{
strcpy(DOSDrives[drive].label_read, "Audio CD ");
read = 1;
read = CDROM_GetLabel(drive, DOSDrives[drive].label_read);
}
else
if (media == CDS_NO_INFO)
{
strcpy(DOSDrives[drive].label_read, " ");
read = 1;
}
CDROM_Close(&wcda);
}
}
if ((!read) && (DOSDrives[drive].flags & DRIVE_READ_VOL_INFO))
if (DOSDrives[drive].flags & DRIVE_READ_VOL_INFO)
{
if (DRIVE_ReadSuperblock(drive,(char *) buff))
ERR("Invalid or unreadable superblock on %s (%c:).\n",
DOSDrives[drive].device, (char)(drive+'A'));
else {
if (DOSDrives[drive].type == TYPE_CDROM)
offs = 40;
else
if (DOSDrives[drive].type == TYPE_FLOPPY ||
DOSDrives[drive].type == TYPE_HD)
offs = 0x2b;
/* FIXME: ISO9660 uses 32-bytes long label. Should we do also? */
/* FIXME: ISO9660 uses a 32 bytes long label. Should we do also? */
if (offs != -1) memcpy(DOSDrives[drive].label_read,buff+offs,11);
DOSDrives[drive].label_read[11]='\0';
read = 1;
@ -683,7 +661,7 @@ int DRIVE_Chdir( int drive, const char *path )
strcpy( buffer, "A:" );
buffer[0] += drive;
TRACE("(%c:,%s)\n", buffer[0], path );
TRACE("(%s,%s)\n", buffer, path );
lstrcpynA( buffer + 2, path, sizeof(buffer) - 2 );
if (!DOSFS_GetFullName( buffer, TRUE, &full_name )) return 0;
@ -769,8 +747,8 @@ int DRIVE_SetLogicalMapping ( int existing_drive, int new_drive )
if ( new->root )
{
TRACE("Can\'t map drive %c to drive %c - drive %c already exists\n",
'A' + existing_drive, 'A' + new_drive, 'A' + new_drive );
TRACE("Can't map drive %c: to already existing drive %c:\n",
'A' + existing_drive, 'A' + new_drive );
/* it is already mapped there, so return success */
if (!strcmp(old->root,new->root))
return 1;
@ -780,14 +758,16 @@ int DRIVE_SetLogicalMapping ( int existing_drive, int new_drive )
new->root = HEAP_strdupA( GetProcessHeap(), 0, old->root );
new->dos_cwd = HEAP_strdupA( GetProcessHeap(), 0, old->dos_cwd );
new->unix_cwd = HEAP_strdupA( GetProcessHeap(), 0, old->unix_cwd );
new->device = HEAP_strdupA( GetProcessHeap(), 0, old->device );
memcpy ( new->label_conf, old->label_conf, 12 );
memcpy ( new->label_read, old->label_read, 12 );
new->serial_conf = old->serial_conf;
new->type = old->type;
new->flags = old->flags;
new->dev = old->dev;
new->ino = old->ino;
TRACE("Drive %c is now equal to drive %c\n",
TRACE("Drive %c: is now equal to drive %c:\n",
'A' + new_drive, 'A' + existing_drive );
return 1;
@ -1093,13 +1073,13 @@ BOOL WINAPI GetDiskFreeSpaceExA( LPCSTR root,
if (total)
{
total->s.HighPart = size.s.HighPart;
total->s.LowPart = size.s.LowPart ;
total->s.LowPart = size.s.LowPart;
}
if (totalfree)
{
totalfree->s.HighPart = available.s.HighPart;
totalfree->s.LowPart = available.s.LowPart ;
totalfree->s.LowPart = available.s.LowPart;
}
if (avail)
@ -1124,7 +1104,7 @@ BOOL WINAPI GetDiskFreeSpaceExA( LPCSTR root,
/* Quick hack, should eventually be fixed to work 100% with
Windows2000 (see comment above). */
avail->s.HighPart = available.s.HighPart;
avail->s.LowPart = available.s.LowPart ;
avail->s.LowPart = available.s.LowPart;
}
return TRUE;
@ -1184,15 +1164,15 @@ UINT16 WINAPI GetDriveType16(
* Type of drive (from Win32 SDK):
*
* DRIVE_UNKNOWN unable to find out anything about the drive
* DRIVE_NO_ROOT_DIR nonexistand root dir
* DRIVE_NO_ROOT_DIR nonexistent root dir
* DRIVE_REMOVABLE the disk can be removed from the machine
* DRIVE_FIXED the disk can not be removed from the machine
* DRIVE_REMOTE network disk
* DRIVE_CDROM CDROM drive
* DRIVE_RAMDISK virtual disk in ram
* DRIVE_RAMDISK virtual disk in RAM
*
* DRIVE_DOESNOTEXIST XXX Not valid return value
* DRIVE_CANNOTDETERMINE XXX Not valid return value
* DRIVE_DOESNOTEXIST FIXME Not valid return value
* DRIVE_CANNOTDETERMINE FIXME Not valid return value
*
* BUGS
*
@ -1297,7 +1277,7 @@ BOOL16 WINAPI SetCurrentDirectory16( LPCSTR dir )
*/
BOOL WINAPI SetCurrentDirectoryA( LPCSTR dir )
{
int olddrive, drive = DRIVE_GetCurrentDrive();
int drive, olddrive = DRIVE_GetCurrentDrive();
if (!dir) {
ERR_(file)("(NULL)!\n");
@ -1305,13 +1285,14 @@ BOOL WINAPI SetCurrentDirectoryA( LPCSTR dir )
}
if (dir[0] && (dir[1]==':'))
{
drive = tolower( *dir ) - 'a';
drive = toupper( *dir ) - 'A';
dir += 2;
}
else
drive = olddrive;
/* WARNING: we need to set the drive before the dir, as DRIVE_Chdir
sets pTask->curdir only if pTask->curdrive is drive */
olddrive = drive; /* in case DRIVE_Chdir fails */
if (!(DRIVE_SetCurrentDrive( drive )))
return FALSE;
/* FIXME: what about empty strings? Add a \\ ? */
@ -1359,7 +1340,7 @@ UINT WINAPI GetLogicalDriveStringsA( UINT len, LPSTR buffer )
return count * 4;
}
else
return (count * 4) + 1;/* account for terminating null */
return (count * 4) + 1; /* account for terminating null */
/* The API tells about these different return values */
}

View File

@ -67,9 +67,11 @@ int CDROM_SetDoor(WINE_CDAUDIO* wcda, int open);
UINT16 CDROM_Audio_GetNumberOfTracks(WINE_CDAUDIO* wcda);
BOOL CDROM_Audio_GetTracksInfo(WINE_CDAUDIO* wcda);
BOOL CDROM_Audio_GetCDStatus(WINE_CDAUDIO* wcda);
WORD CDROM_Data_FindBestVoldesc(int fd);
DWORD CDROM_Audio_GetSerial(WINE_CDAUDIO* wcda);
DWORD CDROM_Data_GetSerial(WINE_CDAUDIO* wcda);
DWORD CDROM_GetSerial(int drive);
DWORD CDROM_GetLabel(int drive, char *label);
#define CDFRAMES_PERSEC 75
#define SECONDS_PERMIN 60

View File

@ -16,6 +16,7 @@
#include "cdrom.h"
#include "drive.h"
#include "debugtools.h"
#include "winbase.h"
DEFAULT_DEBUG_CHANNEL(cdrom);
@ -205,7 +206,7 @@ BOOL CDROM_Audio_GetTracksInfo(WINE_CDAUDIO* wcda)
entry.cdte_track = CDROM_LEADOUT;
#else
#define LEADOUT 0xaa
entry.starting_track = LEADOUT; /* XXX */
entry.starting_track = LEADOUT; /* FIXME */
#endif
else
#ifdef linux
@ -553,7 +554,7 @@ int CDROM_Reset(WINE_CDAUDIO* wcda)
#endif
}
unsigned int get_offs_best_voldesc(int fd)
WORD CDROM_Data_FindBestVoldesc(int fd)
{
BYTE cur_vd_type, max_vd_type = 0;
unsigned int offs, best_offs = 0;
@ -562,7 +563,7 @@ unsigned int get_offs_best_voldesc(int fd)
{
lseek(fd, offs, SEEK_SET);
read(fd, &cur_vd_type, 1);
if (cur_vd_type == 0xff)
if (cur_vd_type == 0xff) /* voldesc set terminator */
break;
if (cur_vd_type > max_vd_type)
{
@ -602,27 +603,41 @@ DWORD CDROM_Audio_GetSerial(WINE_CDAUDIO* wcda)
*/
DWORD CDROM_Data_GetSerial(WINE_CDAUDIO* wcda)
{
unsigned int offs = get_offs_best_voldesc(wcda->unixdev);
WORD offs = CDROM_Data_FindBestVoldesc(wcda->unixdev);
union {
unsigned long val;
unsigned char p[4];
} serial;
BYTE b0 = 0, b1 = 1, b2 = 2, b3 = 3;
serial.val = 0;
if (offs)
{
BYTE buf[2048];
OSVERSIONINFOA ovi;
int i;
lseek(wcda->unixdev,offs,SEEK_SET);
read(wcda->unixdev,buf,2048);
/*
* OK, another braindead one... argh. Just believe it.
* Me$$ysoft chose to reverse the serial number in NT4/W2K.
* It's true and nobody will ever be able to change it.
*/
ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
GetVersionExA(&ovi);
if ((ovi.dwPlatformId == VER_PLATFORM_WIN32_NT)
&& (ovi.dwMajorVersion >= 4))
{
b0 = 3; b1 = 2; b2 = 1; b3 = 0;
}
for(i=0; i<2048; i+=4)
{
/* DON'T optimize this into DWORD !! (breaks overflow) */
serial.p[0] += buf[i+0];
serial.p[1] += buf[i+1];
serial.p[2] += buf[i+2];
serial.p[3] += buf[i+3];
serial.p[b0] += buf[i+b0];
serial.p[b1] += buf[i+b1];
serial.p[b2] += buf[i+b2];
serial.p[b3] += buf[i+b3];
}
}
return serial.val;
@ -655,9 +670,13 @@ DWORD CDROM_GetSerial(int drive)
serial = CDROM_Audio_GetSerial(&wcda);
}
else
if (media > CDS_AUDIO)
if ((media > CDS_AUDIO)
|| (media == -1) /* ioctl() error: ISO9660 image file given ? */
)
/* hopefully a data CD */
serial = CDROM_Data_GetSerial(&wcda);
else
WARN("Strange CD type (%d) or empty ?\n", media);
p = (media == CDS_AUDIO) ? "Audio " :
(media > CDS_AUDIO) ? "Data " : "";
@ -671,3 +690,96 @@ DWORD CDROM_GetSerial(int drive)
return serial;
}
static const char empty_label[] = " ";
/**************************************************************************
* CDROM_Data_GetLabel [internal]
*/
DWORD CDROM_Data_GetLabel(WINE_CDAUDIO* wcda, char *label)
{
#define LABEL_LEN 32+1
WORD offs = CDROM_Data_FindBestVoldesc(wcda->unixdev);
WCHAR label_read[LABEL_LEN]; /* Unicode possible, too */
DWORD unicode_id = 0;
if (offs)
{
if ((lseek(wcda->unixdev, offs+0x58, SEEK_SET) == offs+0x58)
&& (read(wcda->unixdev, &unicode_id, 3) == 3))
{
int ver = (unicode_id & 0xff0000) >> 16;
if ((lseek(wcda->unixdev, offs+0x28, SEEK_SET) != offs+0x28)
|| (read(wcda->unixdev, &label_read, LABEL_LEN) != LABEL_LEN))
goto failure;
if ((LOWORD(unicode_id) == 0x2f25) /* Unicode ID */
&& ((ver == 0x40) || (ver == 0x43) || (ver == 0x45)))
{ /* yippee, unicode */
int i;
WORD ch;
for (i=0; i<LABEL_LEN;i++)
{ /* Motorola -> Intel Unicode conversion :-\ */
ch = label_read[i];
label_read[i] = (ch << 8) | (ch >> 8);
}
lstrcpynWtoA(label, label_read, 11);
}
else
{
strncpy(label, (LPSTR)label_read, 11);
label[11] = '\0';
}
return 0;
}
}
failure:
ERR("error reading label !\n");
strcpy(label, empty_label);
return 0;
}
/**************************************************************************
* CDROM_GetLabel [internal]
*/
DWORD CDROM_GetLabel(int drive, char *label)
{
WINE_CDAUDIO wcda;
DWORD res = 1;
if (!(CDROM_Open(&wcda, drive)))
{
int media = CDROM_GetMediaType(&wcda);
LPSTR p;
if (media == CDS_AUDIO)
{
strcpy(label, "Audio CD ");
}
else
if (media == CDS_NO_INFO)
{
strcpy(label, empty_label);
}
else
if ((media > CDS_AUDIO)
|| (media == -1) /* ioctl() error: ISO9660 image file given ? */
)
/* hopefully a data CD */
CDROM_Data_GetLabel(&wcda, label);
else
{
WARN("Strange CD type (%d) or empty ?\n", media);
strcpy(label, empty_label);
res = 0;
}
p = (media == CDS_AUDIO) ? "Audio " :
(media > CDS_AUDIO) ? "Data " : "";
TRACE("%sCD label is '%s'.\n",
p, label);
CDROM_Close(&wcda);
}
return res;
}

View File

@ -9,19 +9,11 @@
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "wine/winbase16.h"
#include "ldt.h"
#include "drive.h"
#include "msdos.h"
#include "miscemu.h"
#include "module.h"
#include "task.h"
#include "dosexe.h"
#include "heap.h"
/* #define DEBUG_INT */
#include "debugtools.h"
#include "cdrom.h"
@ -582,7 +574,7 @@ static void MSCDEX_Handler(CONTEXT86* context)
MSCDEX_StoreMSF(wcda.dwCurFrame, io_stru + 2);
break;
default:
ERR("CDRom-Driver: Unsupported addressing mode !!\n");
ERR("CD-ROM driver: unsupported addressing mode !!\n");
Error = 0x0c;
}
TRACE(" ----> HEAD LOCATION <%ld>\n", PTR_AT(io_stru, 2, DWORD));