- 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
diff --git a/files/drive.c b/files/drive.c
index e8ab1a0..8f5f010 100644
--- a/files/drive.c
+++ b/files/drive.c
@@ -239,6 +239,7 @@
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 @@
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 @@
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 @@
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;
- }
- else
- if (media == CDS_NO_INFO)
- {
- strcpy(DOSDrives[drive].label_read, " ");
- read = 1;
- }
-
- CDROM_Close(&wcda);
-}
+ read = CDROM_GetLabel(drive, DOSDrives[drive].label_read);
}
- if ((!read) && (DOSDrives[drive].flags & DRIVE_READ_VOL_INFO))
+ else
+ 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 @@
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 @@
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 @@
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;
@@ -825,15 +805,15 @@
else
{
memset(dataptr, 0, nr_sect * 512);
- if (fake_success)
+ if (fake_success)
{
- if (begin == 0 && nr_sect > 1) *(dataptr + 512) = 0xf8;
- if (begin == 1) *dataptr = 0xf8;
- }
- else
- return 0;
+ if (begin == 0 && nr_sect > 1) *(dataptr + 512) = 0xf8;
+ if (begin == 1) *dataptr = 0xf8;
+ }
+ else
+ return 0;
}
- return 1;
+ return 1;
}
@@ -844,7 +824,7 @@
*/
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)
{
@@ -854,10 +834,10 @@
close( fd );
}
else
- if (!(fake_success))
- return 0;
+ if (!(fake_success))
+ return 0;
- return 1;
+ return 1;
}
@@ -1093,13 +1073,13 @@
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 @@
/* 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;
@@ -1176,7 +1156,7 @@
/***********************************************************************
* 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.
*
* RETURNS
@@ -1184,15 +1164,15 @@
* 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 @@
*/
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 @@
}
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 \\ ? */
@@ -1356,10 +1337,10 @@
*p++ = '\0';
}
*p = '\0';
- return count * 4;
+ 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 */
}
diff --git a/include/cdrom.h b/include/cdrom.h
index 0de4797..cde7d22 100644
--- a/include/cdrom.h
+++ b/include/cdrom.h
@@ -67,9 +67,11 @@
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
diff --git a/misc/cdrom.c b/misc/cdrom.c
index 2f2da7d..14a2ffe 100644
--- a/misc/cdrom.c
+++ b/misc/cdrom.c
@@ -16,6 +16,7 @@
#include "cdrom.h"
#include "drive.h"
#include "debugtools.h"
+#include "winbase.h"
DEFAULT_DEBUG_CHANNEL(cdrom);
@@ -205,7 +206,7 @@
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 @@
#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 @@
{
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_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 @@
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 @@
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;
+}
+
diff --git a/msdos/int2f.c b/msdos/int2f.c
index e52149f..acca51b 100644
--- a/msdos/int2f.c
+++ b/msdos/int2f.c
@@ -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 @@
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));