From 3084b58606282ed9b42ac86a6780a08c9fd9d72c Mon Sep 17 00:00:00 2001 From: Andreas Mohr Date: Tue, 25 Jul 2000 20:59:59 +0000 Subject: [PATCH] - 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 --- files/drive.c | 95 ++++++++++++++-------------------- include/cdrom.h | 2 + misc/cdrom.c | 132 ++++++++++++++++++++++++++++++++++++++++++++---- msdos/int2f.c | 10 +--- 4 files changed, 163 insertions(+), 76 deletions(-) diff --git a/files/drive.c b/files/drive.c index e8ab1a02fdd..8f5f010d603 100644 --- a/files/drive.c +++ b/files/drive.c @@ -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; - } - 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 @@ 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; @@ -825,15 +805,15 @@ int DRIVE_RawRead(BYTE drive, DWORD begin, DWORD nr_sect, BYTE *dataptr, BOOL fa 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_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 fd; + int fd; 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 ); } else - if (!(fake_success)) - return 0; + if (!(fake_success)) + return 0; - return 1; + 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; @@ -1176,7 +1156,7 @@ UINT16 WINAPI GetDriveType16( /*********************************************************************** * 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 @@ 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 \\ ? */ @@ -1356,10 +1337,10 @@ UINT WINAPI GetLogicalDriveStringsA( UINT len, LPSTR buffer ) *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 0de4797cd89..cde7d22bfec 100644 --- a/include/cdrom.h +++ b/include/cdrom.h @@ -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 diff --git a/misc/cdrom.c b/misc/cdrom.c index 2f2da7d8f88..14a2ffe113c 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 @@ 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 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 e52149f36ba..acca51b70f2 100644 --- a/msdos/int2f.c +++ b/msdos/int2f.c @@ -9,19 +9,11 @@ #include "config.h" -#include -#include -#include - #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));