- 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 " ); strcpy( DOSDrives[2].label_conf, "Drive C " );
DOSDrives[2].serial_conf = 12345678; DOSDrives[2].serial_conf = 12345678;
DOSDrives[2].type = TYPE_HD; DOSDrives[2].type = TYPE_HD;
DOSDrives[2].device = NULL;
DOSDrives[2].flags = 0; DOSDrives[2].flags = 0;
DRIVE_CurDrive = 2; DRIVE_CurDrive = 2;
} }
@ -456,9 +457,7 @@ int DRIVE_ReadSuperblock (int drive, char * buff)
offs = 0; offs = 0;
break; break;
case TYPE_CDROM: case TYPE_CDROM:
/* FIXME: Maybe we should search for the first data track on the CD, offs = CDROM_Data_FindBestVoldesc(fd);
not just assume that it is the first track */
offs = (off_t)2048*(16+0);
break; break;
default: default:
offs = 0; offs = 0;
@ -473,7 +472,7 @@ int DRIVE_ReadSuperblock (int drive, char * buff)
case TYPE_FLOPPY: case TYPE_FLOPPY:
case TYPE_HD: case TYPE_HD:
if ((buff[0x26]!=0x29) || /* Check for FAT present */ 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 :) */ "FAT" ? (At least FAT12, FAT16 and FAT32 have :) */
memcmp( buff+0x36,"FAT",3)) memcmp( buff+0x36,"FAT",3))
{ {
@ -544,41 +543,20 @@ const char * DRIVE_GetLabel( int drive )
if (!DRIVE_IsValid( drive )) return NULL; if (!DRIVE_IsValid( drive )) return NULL;
if (DRIVE_GetType(drive) == TYPE_CDROM) if (DRIVE_GetType(drive) == TYPE_CDROM)
{ {
WINE_CDAUDIO wcda; read = CDROM_GetLabel(drive, DOSDrives[drive].label_read);
if (!(CDROM_Open(&wcda, drive)))
{
int media = CDROM_GetMediaType(&wcda);
if (media == CDS_AUDIO)
{
strcpy(DOSDrives[drive].label_read, "Audio CD ");
read = 1;
}
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)) else
if (DOSDrives[drive].flags & DRIVE_READ_VOL_INFO)
{ {
if (DRIVE_ReadSuperblock(drive,(char *) buff)) if (DRIVE_ReadSuperblock(drive,(char *) buff))
ERR("Invalid or unreadable superblock on %s (%c:).\n", ERR("Invalid or unreadable superblock on %s (%c:).\n",
DOSDrives[drive].device, (char)(drive+'A')); DOSDrives[drive].device, (char)(drive+'A'));
else { else {
if (DOSDrives[drive].type == TYPE_CDROM)
offs = 40;
else
if (DOSDrives[drive].type == TYPE_FLOPPY || if (DOSDrives[drive].type == TYPE_FLOPPY ||
DOSDrives[drive].type == TYPE_HD) DOSDrives[drive].type == TYPE_HD)
offs = 0x2b; 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); if (offs != -1) memcpy(DOSDrives[drive].label_read,buff+offs,11);
DOSDrives[drive].label_read[11]='\0'; DOSDrives[drive].label_read[11]='\0';
read = 1; read = 1;
@ -683,7 +661,7 @@ int DRIVE_Chdir( int drive, const char *path )
strcpy( buffer, "A:" ); strcpy( buffer, "A:" );
buffer[0] += drive; buffer[0] += drive;
TRACE("(%c:,%s)\n", buffer[0], path ); TRACE("(%s,%s)\n", buffer, path );
lstrcpynA( buffer + 2, path, sizeof(buffer) - 2 ); lstrcpynA( buffer + 2, path, sizeof(buffer) - 2 );
if (!DOSFS_GetFullName( buffer, TRUE, &full_name )) return 0; 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 ) if ( new->root )
{ {
TRACE("Can\'t map drive %c to drive %c - drive %c already exists\n", TRACE("Can't map drive %c: to already existing drive %c:\n",
'A' + existing_drive, 'A' + new_drive, 'A' + new_drive ); 'A' + existing_drive, 'A' + new_drive );
/* it is already mapped there, so return success */ /* it is already mapped there, so return success */
if (!strcmp(old->root,new->root)) if (!strcmp(old->root,new->root))
return 1; return 1;
@ -780,14 +758,16 @@ int DRIVE_SetLogicalMapping ( int existing_drive, int new_drive )
new->root = HEAP_strdupA( GetProcessHeap(), 0, old->root ); new->root = HEAP_strdupA( GetProcessHeap(), 0, old->root );
new->dos_cwd = HEAP_strdupA( GetProcessHeap(), 0, old->dos_cwd ); new->dos_cwd = HEAP_strdupA( GetProcessHeap(), 0, old->dos_cwd );
new->unix_cwd = HEAP_strdupA( GetProcessHeap(), 0, old->unix_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_conf, old->label_conf, 12 );
memcpy ( new->label_read, old->label_read, 12 );
new->serial_conf = old->serial_conf; new->serial_conf = old->serial_conf;
new->type = old->type; new->type = old->type;
new->flags = old->flags; new->flags = old->flags;
new->dev = old->dev; new->dev = old->dev;
new->ino = old->ino; 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 ); 'A' + new_drive, 'A' + existing_drive );
return 1; return 1;
@ -825,15 +805,15 @@ int DRIVE_RawRead(BYTE drive, DWORD begin, DWORD nr_sect, BYTE *dataptr, BOOL fa
else else
{ {
memset(dataptr, 0, nr_sect * 512); memset(dataptr, 0, nr_sect * 512);
if (fake_success) if (fake_success)
{ {
if (begin == 0 && nr_sect > 1) *(dataptr + 512) = 0xf8; if (begin == 0 && nr_sect > 1) *(dataptr + 512) = 0xf8;
if (begin == 1) *dataptr = 0xf8; if (begin == 1) *dataptr = 0xf8;
} }
else else
return 0; return 0;
} }
return 1; return 1;
} }
@ -844,7 +824,7 @@ int DRIVE_RawRead(BYTE drive, DWORD begin, DWORD nr_sect, BYTE *dataptr, BOOL fa
*/ */
int DRIVE_RawWrite(BYTE drive, DWORD begin, DWORD nr_sect, BYTE *dataptr, BOOL fake_success) int DRIVE_RawWrite(BYTE drive, DWORD begin, DWORD nr_sect, BYTE *dataptr, BOOL fake_success)
{ {
int fd; int fd;
if ((fd = DRIVE_OpenDevice( drive, O_RDONLY )) != -1) if ((fd = DRIVE_OpenDevice( drive, O_RDONLY )) != -1)
{ {
@ -854,10 +834,10 @@ int DRIVE_RawWrite(BYTE drive, DWORD begin, DWORD nr_sect, BYTE *dataptr, BOOL f
close( fd ); close( fd );
} }
else else
if (!(fake_success)) if (!(fake_success))
return 0; return 0;
return 1; return 1;
} }
@ -1093,13 +1073,13 @@ BOOL WINAPI GetDiskFreeSpaceExA( LPCSTR root,
if (total) if (total)
{ {
total->s.HighPart = size.s.HighPart; total->s.HighPart = size.s.HighPart;
total->s.LowPart = size.s.LowPart ; total->s.LowPart = size.s.LowPart;
} }
if (totalfree) if (totalfree)
{ {
totalfree->s.HighPart = available.s.HighPart; totalfree->s.HighPart = available.s.HighPart;
totalfree->s.LowPart = available.s.LowPart ; totalfree->s.LowPart = available.s.LowPart;
} }
if (avail) if (avail)
@ -1124,7 +1104,7 @@ BOOL WINAPI GetDiskFreeSpaceExA( LPCSTR root,
/* Quick hack, should eventually be fixed to work 100% with /* Quick hack, should eventually be fixed to work 100% with
Windows2000 (see comment above). */ Windows2000 (see comment above). */
avail->s.HighPart = available.s.HighPart; avail->s.HighPart = available.s.HighPart;
avail->s.LowPart = available.s.LowPart ; avail->s.LowPart = available.s.LowPart;
} }
return TRUE; return TRUE;
@ -1176,7 +1156,7 @@ UINT16 WINAPI GetDriveType16(
/*********************************************************************** /***********************************************************************
* GetDriveTypeA (KERNEL32.208) * GetDriveTypeA (KERNEL32.208)
* *
* Returns the type of the disk drive specified. If root is NULL the * Returns the type of the disk drive specified. If root is NULL the
* root of the current directory is used. * root of the current directory is used.
* *
* RETURNS * RETURNS
@ -1184,15 +1164,15 @@ UINT16 WINAPI GetDriveType16(
* Type of drive (from Win32 SDK): * Type of drive (from Win32 SDK):
* *
* DRIVE_UNKNOWN unable to find out anything about the drive * 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_REMOVABLE the disk can be removed from the machine
* DRIVE_FIXED the disk can not be removed from the machine * DRIVE_FIXED the disk can not be removed from the machine
* DRIVE_REMOTE network disk * DRIVE_REMOTE network disk
* DRIVE_CDROM CDROM drive * DRIVE_CDROM CDROM drive
* DRIVE_RAMDISK virtual disk in ram * DRIVE_RAMDISK virtual disk in RAM
* *
* DRIVE_DOESNOTEXIST XXX Not valid return value * DRIVE_DOESNOTEXIST FIXME Not valid return value
* DRIVE_CANNOTDETERMINE XXX Not valid return value * DRIVE_CANNOTDETERMINE FIXME Not valid return value
* *
* BUGS * BUGS
* *
@ -1297,7 +1277,7 @@ BOOL16 WINAPI SetCurrentDirectory16( LPCSTR dir )
*/ */
BOOL WINAPI SetCurrentDirectoryA( LPCSTR dir ) BOOL WINAPI SetCurrentDirectoryA( LPCSTR dir )
{ {
int olddrive, drive = DRIVE_GetCurrentDrive(); int drive, olddrive = DRIVE_GetCurrentDrive();
if (!dir) { if (!dir) {
ERR_(file)("(NULL)!\n"); ERR_(file)("(NULL)!\n");
@ -1305,13 +1285,14 @@ BOOL WINAPI SetCurrentDirectoryA( LPCSTR dir )
} }
if (dir[0] && (dir[1]==':')) if (dir[0] && (dir[1]==':'))
{ {
drive = tolower( *dir ) - 'a'; drive = toupper( *dir ) - 'A';
dir += 2; dir += 2;
} }
else
drive = olddrive;
/* WARNING: we need to set the drive before the dir, as DRIVE_Chdir /* WARNING: we need to set the drive before the dir, as DRIVE_Chdir
sets pTask->curdir only if pTask->curdrive is drive */ sets pTask->curdir only if pTask->curdrive is drive */
olddrive = drive; /* in case DRIVE_Chdir fails */
if (!(DRIVE_SetCurrentDrive( drive ))) if (!(DRIVE_SetCurrentDrive( drive )))
return FALSE; return FALSE;
/* FIXME: what about empty strings? Add a \\ ? */ /* FIXME: what about empty strings? Add a \\ ? */
@ -1356,10 +1337,10 @@ UINT WINAPI GetLogicalDriveStringsA( UINT len, LPSTR buffer )
*p++ = '\0'; *p++ = '\0';
} }
*p = '\0'; *p = '\0';
return count * 4; return count * 4;
} }
else 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 */ /* 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); UINT16 CDROM_Audio_GetNumberOfTracks(WINE_CDAUDIO* wcda);
BOOL CDROM_Audio_GetTracksInfo(WINE_CDAUDIO* wcda); BOOL CDROM_Audio_GetTracksInfo(WINE_CDAUDIO* wcda);
BOOL CDROM_Audio_GetCDStatus(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_Audio_GetSerial(WINE_CDAUDIO* wcda);
DWORD CDROM_Data_GetSerial(WINE_CDAUDIO* wcda); DWORD CDROM_Data_GetSerial(WINE_CDAUDIO* wcda);
DWORD CDROM_GetSerial(int drive); DWORD CDROM_GetSerial(int drive);
DWORD CDROM_GetLabel(int drive, char *label);
#define CDFRAMES_PERSEC 75 #define CDFRAMES_PERSEC 75
#define SECONDS_PERMIN 60 #define SECONDS_PERMIN 60

View File

@ -16,6 +16,7 @@
#include "cdrom.h" #include "cdrom.h"
#include "drive.h" #include "drive.h"
#include "debugtools.h" #include "debugtools.h"
#include "winbase.h"
DEFAULT_DEBUG_CHANNEL(cdrom); DEFAULT_DEBUG_CHANNEL(cdrom);
@ -205,7 +206,7 @@ BOOL CDROM_Audio_GetTracksInfo(WINE_CDAUDIO* wcda)
entry.cdte_track = CDROM_LEADOUT; entry.cdte_track = CDROM_LEADOUT;
#else #else
#define LEADOUT 0xaa #define LEADOUT 0xaa
entry.starting_track = LEADOUT; /* XXX */ entry.starting_track = LEADOUT; /* FIXME */
#endif #endif
else else
#ifdef linux #ifdef linux
@ -553,7 +554,7 @@ int CDROM_Reset(WINE_CDAUDIO* wcda)
#endif #endif
} }
unsigned int get_offs_best_voldesc(int fd) WORD CDROM_Data_FindBestVoldesc(int fd)
{ {
BYTE cur_vd_type, max_vd_type = 0; BYTE cur_vd_type, max_vd_type = 0;
unsigned int offs, best_offs = 0; unsigned int offs, best_offs = 0;
@ -562,7 +563,7 @@ unsigned int get_offs_best_voldesc(int fd)
{ {
lseek(fd, offs, SEEK_SET); lseek(fd, offs, SEEK_SET);
read(fd, &cur_vd_type, 1); read(fd, &cur_vd_type, 1);
if (cur_vd_type == 0xff) if (cur_vd_type == 0xff) /* voldesc set terminator */
break; break;
if (cur_vd_type > max_vd_type) 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) DWORD CDROM_Data_GetSerial(WINE_CDAUDIO* wcda)
{ {
unsigned int offs = get_offs_best_voldesc(wcda->unixdev); WORD offs = CDROM_Data_FindBestVoldesc(wcda->unixdev);
union { union {
unsigned long val; unsigned long val;
unsigned char p[4]; unsigned char p[4];
} serial; } serial;
BYTE b0 = 0, b1 = 1, b2 = 2, b3 = 3;
serial.val = 0; serial.val = 0;
if (offs) if (offs)
{ {
BYTE buf[2048]; BYTE buf[2048];
OSVERSIONINFOA ovi;
int i; int i;
lseek(wcda->unixdev,offs,SEEK_SET); lseek(wcda->unixdev,offs,SEEK_SET);
read(wcda->unixdev,buf,2048); 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) for(i=0; i<2048; i+=4)
{ {
/* DON'T optimize this into DWORD !! (breaks overflow) */ /* DON'T optimize this into DWORD !! (breaks overflow) */
serial.p[0] += buf[i+0]; serial.p[b0] += buf[i+b0];
serial.p[1] += buf[i+1]; serial.p[b1] += buf[i+b1];
serial.p[2] += buf[i+2]; serial.p[b2] += buf[i+b2];
serial.p[3] += buf[i+3]; serial.p[b3] += buf[i+b3];
} }
} }
return serial.val; return serial.val;
@ -655,9 +670,13 @@ DWORD CDROM_GetSerial(int drive)
serial = CDROM_Audio_GetSerial(&wcda); serial = CDROM_Audio_GetSerial(&wcda);
} }
else else
if (media > CDS_AUDIO) if ((media > CDS_AUDIO)
|| (media == -1) /* ioctl() error: ISO9660 image file given ? */
)
/* hopefully a data CD */ /* hopefully a data CD */
serial = CDROM_Data_GetSerial(&wcda); serial = CDROM_Data_GetSerial(&wcda);
else
WARN("Strange CD type (%d) or empty ?\n", media);
p = (media == CDS_AUDIO) ? "Audio " : p = (media == CDS_AUDIO) ? "Audio " :
(media > CDS_AUDIO) ? "Data " : ""; (media > CDS_AUDIO) ? "Data " : "";
@ -671,3 +690,96 @@ DWORD CDROM_GetSerial(int drive)
return serial; 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 "config.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "wine/winbase16.h" #include "wine/winbase16.h"
#include "ldt.h"
#include "drive.h" #include "drive.h"
#include "msdos.h"
#include "miscemu.h" #include "miscemu.h"
#include "module.h" #include "module.h"
#include "task.h" #include "task.h"
#include "dosexe.h"
#include "heap.h"
/* #define DEBUG_INT */ /* #define DEBUG_INT */
#include "debugtools.h" #include "debugtools.h"
#include "cdrom.h" #include "cdrom.h"
@ -582,7 +574,7 @@ static void MSCDEX_Handler(CONTEXT86* context)
MSCDEX_StoreMSF(wcda.dwCurFrame, io_stru + 2); MSCDEX_StoreMSF(wcda.dwCurFrame, io_stru + 2);
break; break;
default: default:
ERR("CDRom-Driver: Unsupported addressing mode !!\n"); ERR("CD-ROM driver: unsupported addressing mode !!\n");
Error = 0x0c; Error = 0x0c;
} }
TRACE(" ----> HEAD LOCATION <%ld>\n", PTR_AT(io_stru, 2, DWORD)); TRACE(" ----> HEAD LOCATION <%ld>\n", PTR_AT(io_stru, 2, DWORD));