it's mainly a rewrite without using kernel32 internals
the most important modification is that modifying a drive serial number is no longer possible. there's no exported function from kernel32 to do so. Anyway, I don't think it's a big deal (it was only useful on floppies, which are less and less used).
If needed we could copy the existing kernel32 code to dlls/winedos if needed
only the find{first|next} functions remain in msdos/int21.c which will be (soon) history.
A+ -- Eric Pouech
Name: int21 ChangeLog: -t moved a few more int21 calls to dlls/winedos (setting drive serial# has been disabled) -t added volume management prototypes to include/winebase.h -t started DefineDosDevice (needed by first item in this list) License: X11 GenDate: 2003/11/09 18:21:10 UTC ModifiedFiles: dlls/winedos/int21.c files/drive.c include/winbase.h msdos/int21.c =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/dlls/winedos/int21.c,v retrieving revision 1.45 diff -u -u -r1.45 int21.c --- dlls/winedos/int21.c 3 Nov 2003 22:13:25 -0000 1.45 +++ dlls/winedos/int21.c 9 Nov 2003 18:16:12 -0000 @@ -26,6 +26,10 @@ #include "config.h" #include <stdarg.h> +#include <stdio.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif #include "windef.h" #include "winbase.h" @@ -58,6 +62,13 @@ #include "pshpack1.h" +struct DosHeap { + BYTE mediaID; + BYTE biosdate[8]; +}; +static struct DosHeap *heap; +static WORD DosHeapHandle; + /* * Extended Drive Parameter Block. * This structure is compatible with standard DOS4+ DPB and @@ -161,13 +172,40 @@ #include "poppack.h" +static BOOL INT21_CreateHeap(void) +{ + if (!(DosHeapHandle = GlobalAlloc16(GMEM_FIXED,sizeof(struct DosHeap)))) + { + WARN("Out of memory\n"); + return FALSE; + } + heap = (struct DosHeap *) GlobalLock16(DosHeapHandle); + strcpy(heap->biosdate, "01/01/80"); + return TRUE; +} + +/* Many calls translate a drive argument like this: + drive number (00h = default, 01h = A:, etc) + */ +/****************************************************************** + * INT21_DriveName + * + * Many calls translate a drive argument like this: + * drive number (00h = default, 01h = A:, etc) + */ +static const char *INT21_DriveName(int drive) +{ + if (drive > 0) return wine_dbg_sprintf( "%c:", 'A' + drive - 1 ); + return "default"; +} + /*********************************************************************** * INT21_GetCurrentDrive * * Return current drive using scheme (0=A:, 1=B:, 2=C:, ...) or * MAX_DOS_DRIVES on error. */ -static BYTE INT21_GetCurrentDrive() +static BYTE INT21_GetCurrentDrive(void) { WCHAR current_directory[MAX_PATH]; @@ -2092,6 +2130,50 @@ SET_BX( context, DOSVM_psp ); } +static void CreateBPB(int drive, BYTE *data, BOOL16 limited) +/* limited == TRUE is used with INT 0x21/0x440d */ +{ + if (drive > 1) + { + setword(data, 512); + data[2] = 2; + setword(&data[3], 0); + data[5] = 2; + setword(&data[6], 240); + setword(&data[8], 64000); + data[0x0a] = 0xf8; + setword(&data[0x0b], 40); + setword(&data[0x0d], 56); + setword(&data[0x0f], 2); + setword(&data[0x11], 0); + if (!limited) + { + setword(&data[0x1f], 800); + data[0x21] = 5; + setword(&data[0x22], 1); + } + } + else + { /* 1.44mb */ + setword(data, 512); + data[2] = 2; + setword(&data[3], 0); + data[5] = 2; + setword(&data[6], 240); + setword(&data[8], 2880); + data[0x0a] = 0xf8; + setword(&data[0x0b], 6); + setword(&data[0x0d], 18); + setword(&data[0x0f], 2); + setword(&data[0x11], 0); + if (!limited) + { + setword(&data[0x1f], 80); + data[0x21] = 7; + setword(&data[0x22], 2); + } + } +} /*********************************************************************** * INT21_Ioctl_Block @@ -2176,7 +2258,24 @@ break; case 0x0860: /* get device parameters */ - INT_Int21Handler( context ); + /* used by w4wgrp's winfile */ + memset(dataptr, 0, 0x20); /* DOS 6.22 uses 0x20 bytes */ + dataptr[0] = 0x04; + dataptr[6] = 0; /* media type */ + if (drive > 1) + { + dataptr[1] = 0x05; /* fixed disk */ + setword(&dataptr[2], 0x01); /* non removable */ + setword(&dataptr[4], 0x300); /* # of cylinders */ + } + else + { + dataptr[1] = 0x07; /* block dev, floppy */ + setword(&dataptr[2], 0x02); /* removable */ + setword(&dataptr[4], 80); /* # of cylinders */ + } + CreateBPB(drive, &dataptr[7], TRUE); + RESET_CFLAG(context); break; case 0x0861: /* read logical device track */ @@ -2198,7 +2297,18 @@ break; case 0x0866: /* get volume serial number */ - INT_Int21Handler( context ); + { + char label[12],fsname[9],path[4]; + DWORD serial; + + path[0] = drive+'A'; + strcpy(path + 1, ":\\"); + GetVolumeInformationA(path,label,12,&serial,NULL,NULL,fsname,9); + *(WORD*)dataptr = 0; + memcpy(dataptr+2,&serial,4); + memcpy(dataptr+6,label ,11); + memcpy(dataptr+17,fsname,8); + } break; case 0x086a: /* unlock logical volume */ @@ -2207,11 +2317,16 @@ break; case 0x086f: /* get drive map information */ - INT_Int21Handler( context ); + memset(dataptr+1, '\0', dataptr[0]-1); + dataptr[1] = dataptr[0]; + dataptr[2] = 0x07; /* protected mode driver; no eject; no notification */ + dataptr[3] = 0xFF; /* no physical drive */ break; case 0x0872: - INT_Int21Handler( context ); + /* Trail on error implementation */ + SET_AX( context, drivetype == DRIVE_UNKNOWN ? 0x0f : 0x01 ); + SET_CFLAG(context); /* Seems to be set all the time */ break; default: @@ -2227,7 +2342,19 @@ break; case 0x0f: /* SET LOGICAL DRIVE MAP */ - INT_Int21Handler( context ); + { + char dev[3], target[4]; + + TRACE("IOCTL - SET LOGICAL DRIVE MAP for drive %s\n", + INT21_DriveName( BL_reg(context))); + sprintf(dev, "%c:", 'A' + drive); + sprintf(target, "%c:\\", 'A' + drive + 1); + if (!DefineDosDeviceA(DDD_RAW_TARGET_PATH, dev, target)) + { + SET_CFLAG(context); + SET_AX( context, 0x000F ); /* invalid drive */ + } + } break; case 0x11: /* QUERY GENERIC IOCTL CAPABILITY */ @@ -2729,6 +2861,128 @@ /*********************************************************************** + * INT21_NetworkFunc + * + * Handler for: + * - function 0x5e + */ +static BOOL INT21_NetworkFunc (CONTEXT86 *context) +{ + switch (AL_reg(context)) + { + case 0x00: /* Get machine name. */ + { + char *dst = CTX_SEG_OFF_TO_LIN (context,context->SegDs,context->Edx); + TRACE("getting machine name to %p\n", dst); + if (gethostname (dst, 15)) + { + WARN("failed!\n"); + SetLastError( ER_NoNetwork ); + return TRUE; + } + else + { + int len = strlen (dst); + while (len < 15) + dst[len++] = ' '; + dst[15] = 0; + SET_CH( context, 1 ); /* Valid */ + SET_CL( context, 1 ); /* NETbios number??? */ + TRACE("returning %s\n", debugstr_an (dst, 16)); + return FALSE; + } + } + + default: + SetLastError( ER_NoNetwork ); + return TRUE; + } +} + +/****************************************************************** + * INT21_GetDiskSerialNumber + * + */ +static int INT21_GetDiskSerialNumber( CONTEXT86 *context ) +{ + BYTE *dataptr = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx); + char path[] = {'A',':',0}; + + path[0] += BL_reg(context) ? BL_reg(context) - 1 : INT21_GetCurrentDrive(); + if (!GetVolumeInformationA( path, (char *)(dataptr + 6), 11, + (DWORD *)(dataptr + 2), + NULL, NULL, NULL, 0)) + { + SetLastError( ERROR_INVALID_DRIVE ); + return 0; + } + + *(WORD *)dataptr = 0; + strncpy(dataptr + 0x11, "FAT16 ", 8); + return 1; +} + + +/****************************************************************** + * INT21_SetDiskSerialNumber + * + */ +static int INT21_SetDiskSerialNumber( CONTEXT86 *context ) +{ +#if 0 + BYTE *dataptr = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx); + int drive = BL_reg(context) ? BL_reg(context) - 1 : INT21_GetCurrentDrive(); + + if (!is_valid_drive(drive)) + { + SetLastError( ERROR_INVALID_DRIVE ); + return 0; + } + + DRIVE_SetSerialNumber( drive, *(DWORD *)(dataptr + 2) ); + return 1; +#else + FIXME("Setting drive serial number is no longer supported\n"); + SetLastError( ERROR_NOT_SUPPORTED ); + return 0; +#endif +} + + +/****************************************************************** + * INT21_GetFreeDiskSpace + * + */ +static int INT21_GetFreeDiskSpace( CONTEXT86 *context ) +{ + DWORD cluster_sectors, sector_bytes, free_clusters, total_clusters; + char root[] = "A:\\"; + + *root += BL_reg(context) ? BL_reg(context) - 1 : INT21_GetCurrentDrive(); + if (!GetDiskFreeSpaceA( root, &cluster_sectors, §or_bytes, + &free_clusters, &total_clusters )) return 0; + SET_AX( context, cluster_sectors ); + SET_BX( context, free_clusters ); + SET_CX( context, sector_bytes ); + SET_DX( context, total_clusters ); + return 1; +} + +/****************************************************************** + * INT21_GetDriveAllocInfo + * + */ +static int INT21_GetDriveAllocInfo( CONTEXT86 *context ) +{ + if (!INT21_GetFreeDiskSpace( context )) return 0; + if (!heap && !INT21_CreateHeap()) return 0; + heap->mediaID = 0xf0; + context->SegDs = DosHeapHandle; + SET_BX( context, (int)&heap->mediaID - (int)heap ); + return 1; +} + +/*********************************************************************** * INT21_GetExtendedError */ static void INT21_GetExtendedError( CONTEXT86 *context ) @@ -2843,6 +3097,34 @@ SET_CH( context, locus ); } +static BOOL INT21_CreateTempFile( CONTEXT86 *context ) +{ + static int counter = 0; + char *name = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx ); + char *p = name + strlen(name); + + /* despite what Ralf Brown says, some programs seem to call without + * ending backslash (DOS accepts that, so we accept it too) */ + if ((p == name) || (p[-1] != '\\')) *p++ = '\\'; + + for (;;) + { + sprintf( p, "wine%04x.%03d", (int)getpid(), counter ); + counter = (counter + 1) % 1000; + + SET_AX( context, + Win32HandleToDosFileHandle( + CreateFileA( name, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + CREATE_NEW, 0, 0 ) ) ); + if (AX_reg(context) != HFILE_ERROR16) + { + TRACE("created %s\n", name ); + return TRUE; + } + if (GetLastError() != ERROR_FILE_EXISTS) return FALSE; + } +} /*********************************************************************** * DOSVM_Int21Handler @@ -3101,8 +3383,12 @@ break; case 0x1b: /* GET ALLOCATION INFORMATION FOR DEFAULT DRIVE */ + SET_DL( context, 0 ); + if (!INT21_GetDriveAllocInfo(context)) SET_AX( context, 0xffff ); + break; + case 0x1c: /* GET ALLOCATION INFORMATION FOR SPECIFIC DRIVE */ - INT_Int21Handler( context ); + if (!INT21_GetDriveAllocInfo(context)) SET_AX( context, 0xffff ); break; case 0x1d: /* NULL FUNCTION FOR CP/M COMPATIBILITY */ @@ -3356,7 +3642,9 @@ break; case 0x36: /* GET FREE DISK SPACE */ - INT_Int21Handler( context ); + TRACE("GET FREE DISK SPACE FOR DRIVE %s\n", + INT21_DriveName( DL_reg(context))); + if (!INT21_GetFreeDiskSpace(context)) SET_AX( context, 0xffff ); break; case 0x37: /* SWITCHAR */ @@ -3834,7 +4122,8 @@ break; case 0x5a: /* CREATE TEMPORARY FILE */ - INT_Int21Handler( context ); + TRACE("CREATE TEMPORARY FILE\n"); + bSetDOSExtendedError = !INT21_CreateTempFile(context); break; case 0x5b: /* CREATE NEW FILE */ @@ -3881,11 +4170,26 @@ break; case 0x5e: /* NETWORK 5E */ + bSetDOSExtendedError = INT21_NetworkFunc( context); + break; + case 0x5f: /* NETWORK 5F */ - case 0x60: /* "TRUENAME" - CANONICALIZE FILENAME OR PATH */ INT_Int21Handler( context ); break; + case 0x60: /* "TRUENAME" - CANONICALIZE FILENAME OR PATH */ + TRACE("TRUENAME %s\n", + (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs,context->Esi)); + { + if (!GetFullPathNameA( CTX_SEG_OFF_TO_LIN(context, context->SegDs, + context->Esi), 128, + CTX_SEG_OFF_TO_LIN(context, context->SegEs, + context->Edi),NULL)) + bSetDOSExtendedError = TRUE; + else SET_AX( context, 0 ); + } + break; + case 0x61: /* UNUSED */ SET_AL( context, 0 ); break; @@ -3942,7 +4246,22 @@ break; case 0x69: /* DISK SERIAL NUMBER */ - INT_Int21Handler( context ); + switch (AL_reg(context)) + { + case 0x00: + TRACE("GET DISK SERIAL NUMBER for drive %s\n", + INT21_DriveName(BL_reg(context))); + if (!INT21_GetDiskSerialNumber(context)) bSetDOSExtendedError = TRUE; + else SET_AX( context, 0 ); + break; + + case 0x01: + TRACE("SET DISK SERIAL NUMBER for drive %s\n", + INT21_DriveName(BL_reg(context))); + if (!INT21_SetDiskSerialNumber(context)) bSetDOSExtendedError = TRUE; + else SET_AX( context, 1 ); + break; + } break; case 0x6a: /* COMMIT FILE */ Index: files/drive.c =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/files/drive.c,v retrieving revision 1.100 diff -u -u -r1.100 drive.c --- files/drive.c 15 Oct 2003 03:47:53 -0000 1.100 +++ files/drive.c 9 Nov 2003 16:06:43 -0000 @@ -1283,21 +963,28 @@ /*********************************************************************** - * DRIVE_SetLogicalMapping + * DefineDosDeviceA (KERNEL32.@) */ -int DRIVE_SetLogicalMapping ( int existing_drive, int new_drive ) +BOOL WINAPI DefineDosDeviceA(DWORD flags,LPCSTR devname,LPCSTR targetpath) { - /* If new_drive is already valid, do nothing and return 0 - otherwise, copy DOSDrives[existing_drive] to DOSDrives[new_drive] */ - DOSDRIVE *old, *new; - old = DOSDrives + existing_drive; - new = DOSDrives + new_drive; + /* this is a temporary hack for int21 support. better implementation has to be done */ + if (flags != DDD_RAW_TARGET_PATH || + !(toupper(devname[0]) >= 'A' && toupper(devname[0]) <= 'Z') || + devname[1] != ':' || devname[2] != 0 || + !(toupper(targetpath[0]) >= 'A' && toupper(targetpath[0]) <= 'Z') || + targetpath[1] != ':' || targetpath[2] != '\\' || targetpath[3] != 0) + { + FIXME("(0x%08lx,%s,%s),stub!\n", flags, devname, targetpath); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + + old = DOSDrives + devname[0] - 'A'; + new = DOSDrives + targetpath[0] - 'A'; - if ((existing_drive < 0) || (existing_drive >= MAX_DOS_DRIVES) || - !old->root || - (new_drive < 0) || (new_drive >= MAX_DOS_DRIVES)) + if (!old->root) { SetLastError( ERROR_INVALID_DRIVE ); return 0; @@ -1306,7 +993,7 @@ if ( new->root ) { TRACE("Can't map drive %c: to already existing drive %c:\n", - 'A' + existing_drive, 'A' + new_drive ); + devname[0], targetpath[0] ); /* it is already mapped there, so return success */ if (!strcmp(old->root,new->root)) return 1; @@ -1327,7 +1014,7 @@ new->ino = old->ino; TRACE("Drive %c: is now equal to drive %c:\n", - 'A' + new_drive, 'A' + existing_drive ); + targetpath[0], devname[0] ); return 1; } @@ -2126,8 +1781,8 @@ /*********************************************************************** * GetVolumeNameForVolumeMountPointW (KERNEL32.@) */ -DWORD WINAPI GetVolumeNameForVolumeMountPointW(LPWSTR str, DWORD a, DWORD b) +BOOL WINAPI GetVolumeNameForVolumeMountPointW(LPCWSTR str, LPWSTR dst, DWORD size) { - FIXME("(%s, %lx, %lx): stub\n", debugstr_w(str), a, b); + FIXME("(%s, %p, %lx): stub\n", debugstr_w(str), dst, size); return 0; } Index: include/winbase.h =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/include/winbase.h,v retrieving revision 1.199 diff -u -u -r1.199 winbase.h --- include/winbase.h 4 Nov 2003 04:52:54 -0000 1.199 +++ include/winbase.h 9 Nov 2003 15:53:06 -0000 @@ -1090,6 +1090,13 @@ BOOL WINAPI GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType ); #define GetBinaryType WINELIB_NAME_AW(GetBinaryType) +/* flags for DefineDosDevice */ +#define DDD_RAW_TARGET_PATH 0x00000001 +#define DDD_REMOVE_DEFINITION 0x00000002 +#define DDD_EXACT_MATCH_ON_REMOVE 0x00000004 +#define DDD_NO_BROADCAST_SYSTEM 0x00000008 +#define DDD_LUID_BROADCAST_DRIVE 0x00000010 + BOOL WINAPI AddAccessAllowedAce(PACL,DWORD,DWORD,PSID); PVOID WINAPI AddVectoredExceptionHandler(ULONG,PVECTORED_EXCEPTION_HANDLER); BOOL WINAPI AttachThreadInput(DWORD,DWORD,BOOL); @@ -1182,9 +1189,15 @@ void WINAPI DebugBreak(void); BOOL WINAPI DebugBreakProcess(HANDLE); BOOL WINAPI DebugSetProcessKillOnExit(BOOL); +BOOL WINAPI DefineDosDeviceA(DWORD,LPCSTR,LPCSTR); +BOOL WINAPI DefineDosDeviceW(DWORD,LPCSTR,LPCSTR); +#define DefineDosDevice WINELIB_NAME_AW(DefineDosDevice) void WINAPI DeleteFiber(LPVOID); BOOL WINAPI DeleteTimerQueueEx(HANDLE,HANDLE); BOOL WINAPI DeleteTimerQueueTimer(HANDLE,HANDLE,HANDLE); +BOOL WINAPI DeleteVolumeMountPointA(LPCSTR); +BOOL WINAPI DeleteVolumeMountPointW(LPCWSTR); +#define DeleteVolumeMountPoint WINELIB_NAME_AW(DeleteVolumeMountPoint) BOOL WINAPI DeregisterEventSource(HANDLE); BOOL WINAPI DeviceIoControl(HANDLE,DWORD,LPVOID,DWORD,LPVOID,DWORD,LPDWORD,LPOVERLAPPED); BOOL WINAPI DisableThreadLibraryCalls(HMODULE); @@ -1223,6 +1236,20 @@ HRSRC WINAPI FindResourceExA(HMODULE,LPCSTR,LPCSTR,WORD); HRSRC WINAPI FindResourceExW(HMODULE,LPCWSTR,LPCWSTR,WORD); #define FindResourceEx WINELIB_NAME_AW(FindResourceEx) +HANDLE WINAPI FindFirstVolumeA(LPSTR,DWORD); +HANDLE WINAPI FindFirstVolumeW(LPWSTR,DWORD); +#define FindFirstVolume WINELIB_NAME_AW(FindFirstVolume) +HANDLE WINAPI FindFirstVolumeMountPointA(LPCSTR,LPSTR,DWORD); +HANDLE WINAPI FindFirstVolumeMountPointW(LPCWSTR,LPWSTR,DWORD); +#define FindFirstVolumeMountPoint WINELIB_NAME_AW(FindFirstVolumeMountPoint) +BOOL WINAPI FindNextVolumeA(HANDLE,LPSTR,DWORD); +BOOL WINAPI FindNextVolumeW(HANDLE,LPWSTR,DWORD); +#define FindNextVolume WINELIB_NAME_AW(FindNextVolume) +BOOL WINAPI FindNextVolumeMountPointA(HANDLE,LPSTR,DWORD); +BOOL WINAPI FindNextVolumeMountPointW(HANDLE,LPWSTR,DWORD); +#define FindNextVolumeMountPoint WINELIB_NAME_AW(FindNextVolumeMountPoint) +BOOL WINAPI FindVolumeClose(HANDLE); +BOOL WINAPI FindVolumeMountPointClose(HANDLE); BOOL WINAPI FlushFileBuffers(HANDLE); BOOL WINAPI FlushViewOfFile(LPCVOID,SIZE_T); DWORD WINAPI FormatMessageA(DWORD,LPCVOID,DWORD,DWORD,LPSTR,DWORD,va_list*); @@ -1322,6 +1349,15 @@ BOOL WINAPI GetUserNameA(LPSTR,LPDWORD); BOOL WINAPI GetUserNameW(LPWSTR,LPDWORD); #define GetUserName WINELIB_NAME_AW(GetUserName) +BOOL WINAPI GetVolumeNameForVolumeMountPointA(LPCSTR,LPSTR,DWORD); +BOOL WINAPI GetVolumeNameForVolumeMountPointW(LPCWSTR,LPWSTR,DWORD); +#define GetVolumeNameForVolumeMountPoint WINELIB_NAME_AW(GetVolumeNameForVolumeMountPoint) +BOOL WINAPI GetVolumePathNameA(LPCSTR,LPSTR,DWORD); +BOOL WINAPI GetVolumePathNameW(LPCWSTR,LPWSTR,DWORD); +#define GetVolumePathName WINELIB_NAME_AW(GetVolumePathName) +BOOL WINAPI GetVolumePathNamesForVolumeNameA(LPCSTR,LPSTR,DWORD,PDWORD); +BOOL WINAPI GetVolumePathNamesForVolumeNameW(LPCWSTR,LPWSTR,DWORD,PDWORD); +#define GetVolumePathNamesForVolumeName WINELIB_NAME_AW(GetVolumePathNamesForVolumeName) VOID WINAPI GlobalMemoryStatus(LPMEMORYSTATUS); LPVOID WINAPI HeapAlloc(HANDLE,DWORD,SIZE_T); SIZE_T WINAPI HeapCompact(HANDLE,DWORD); @@ -1470,6 +1506,9 @@ BOOL WINAPI SetThreadPriorityBoost(HANDLE,BOOL); BOOL WINAPI SetThreadToken(PHANDLE,HANDLE); BOOL WINAPI SetTimeZoneInformation(const LPTIME_ZONE_INFORMATION); +BOOL WINAPI SetVolumeMountPointA(LPCSTR,LPCSTR); +BOOL WINAPI SetVolumeMountPointW(LPCSTR,LPCSTR); +#define SetVolumeMountPoint WINELIB_NAME_AW(SetVolumeMountPoint) BOOL WINAPI SetWaitableTimer(HANDLE,const LARGE_INTEGER*,LONG,PTIMERAPCROUTINE,LPVOID,BOOL); BOOL WINAPI SetupComm(HANDLE,DWORD,DWORD); DWORD WINAPI SignalObjectAndWait(HANDLE,HANDLE,DWORD,BOOL); Index: msdos/int21.c =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/msdos/int21.c,v retrieving revision 1.100 diff -u -u -r1.100 int21.c --- msdos/int21.c 27 Oct 2003 22:06:10 -0000 1.100 +++ msdos/int21.c 9 Nov 2003 18:20:26 -0000 @@ -70,30 +70,10 @@ #define LOCK_NB 8 #endif - #define DOS_GET_DRIVE(reg) ((reg) ? (reg) - 1 : DRIVE_GetCurrentDrive()) -struct DosHeap { - BYTE mediaID; - BYTE biosdate[8]; -}; -static struct DosHeap *heap; -static WORD DosHeapHandle; - extern char TempDirectory[]; -static BOOL INT21_CreateHeap(void) -{ - if (!(DosHeapHandle = GlobalAlloc16(GMEM_FIXED,sizeof(struct DosHeap)))) - { - WARN("Out of memory\n"); - return FALSE; - } - heap = (struct DosHeap *) GlobalLock16(DosHeapHandle); - strcpy(heap->biosdate, "01/01/80"); - return TRUE; -} - static BYTE *GetCurrentDTA( CONTEXT86 *context ) { TDB *pTask = GlobalLock16(GetCurrentTask()); @@ -104,146 +84,6 @@ } -static void CreateBPB(int drive, BYTE *data, BOOL16 limited) -/* limited == TRUE is used with INT 0x21/0x440d */ -{ - if (drive > 1) { - setword(data, 512); - data[2] = 2; - setword(&data[3], 0); - data[5] = 2; - setword(&data[6], 240); - setword(&data[8], 64000); - data[0x0a] = 0xf8; - setword(&data[0x0b], 40); - setword(&data[0x0d], 56); - setword(&data[0x0f], 2); - setword(&data[0x11], 0); - if (!limited) { - setword(&data[0x1f], 800); - data[0x21] = 5; - setword(&data[0x22], 1); - } - } else { /* 1.44mb */ - setword(data, 512); - data[2] = 2; - setword(&data[3], 0); - data[5] = 2; - setword(&data[6], 240); - setword(&data[8], 2880); - data[0x0a] = 0xf8; - setword(&data[0x0b], 6); - setword(&data[0x0d], 18); - setword(&data[0x0f], 2); - setword(&data[0x11], 0); - if (!limited) { - setword(&data[0x1f], 80); - data[0x21] = 7; - setword(&data[0x22], 2); - } - } -} - -static int INT21_GetFreeDiskSpace( CONTEXT86 *context ) -{ - DWORD cluster_sectors, sector_bytes, free_clusters, total_clusters; - char root[] = "A:\\"; - - *root += DOS_GET_DRIVE( DL_reg(context) ); - if (!GetDiskFreeSpaceA( root, &cluster_sectors, §or_bytes, - &free_clusters, &total_clusters )) return 0; - SET_AX( context, cluster_sectors ); - SET_BX( context, free_clusters ); - SET_CX( context, sector_bytes ); - SET_DX( context, total_clusters ); - return 1; -} - -static int INT21_GetDriveAllocInfo( CONTEXT86 *context ) -{ - if (!INT21_GetFreeDiskSpace( context )) return 0; - if (!heap && !INT21_CreateHeap()) return 0; - heap->mediaID = 0xf0; - context->SegDs = DosHeapHandle; - SET_BX( context, (int)&heap->mediaID - (int)heap ); - return 1; -} - -static BOOL ioctlGenericBlkDevReq( CONTEXT86 *context ) -{ - BYTE *dataptr = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx); - int drive = DOS_GET_DRIVE( BL_reg(context) ); - - if (!DRIVE_IsValid(drive)) - { - SetLastError( ERROR_FILE_NOT_FOUND ); - return TRUE; - } - - if (CH_reg(context) != 0x08) - { - INT_BARF( context, 0x21 ); - return FALSE; - } - - switch (CL_reg(context)) - { - case 0x60: /* get device parameters */ - /* used by w4wgrp's winfile */ - memset(dataptr, 0, 0x20); /* DOS 6.22 uses 0x20 bytes */ - dataptr[0] = 0x04; - dataptr[6] = 0; /* media type */ - if (drive > 1) - { - dataptr[1] = 0x05; /* fixed disk */ - setword(&dataptr[2], 0x01); /* non removable */ - setword(&dataptr[4], 0x300); /* # of cylinders */ - } - else - { - dataptr[1] = 0x07; /* block dev, floppy */ - setword(&dataptr[2], 0x02); /* removable */ - setword(&dataptr[4], 80); /* # of cylinders */ - } - CreateBPB(drive, &dataptr[7], TRUE); - RESET_CFLAG(context); - break; - - case 0x66:/* get disk serial number */ - { - char label[12],fsname[9],path[4]; - DWORD serial; - - strcpy(path,"x:\\");path[0]=drive+'A'; - GetVolumeInformationA( - path,label,12,&serial,NULL,NULL,fsname,9 - ); - *(WORD*)dataptr = 0; - memcpy(dataptr+2,&serial,4); - memcpy(dataptr+6,label ,11); - memcpy(dataptr+17,fsname,8); - } - break; - - case 0x6f: - memset(dataptr+1, '\0', dataptr[0]-1); - dataptr[1] = dataptr[0]; - dataptr[2] = 0x07; /* protected mode driver; no eject; no notification */ - dataptr[3] = 0xFF; /* no physical drive */ - break; - - case 0x72: - /* Trail on error implementation */ - SET_AX( context, GetDriveType16(BL_reg(context)) == DRIVE_UNKNOWN ? 0x0f : 0x01 ); - SET_CFLAG(context); /* Seems to be set all the time */ - break; - - default: - INT_BARF( context, 0x21 ); - } - return FALSE; -} - static void INT21_ParseFileNameIntoFCB( CONTEXT86 *context ) { char *filename = @@ -289,25 +129,6 @@ } -/* Many calls translate a drive argument like this: - drive number (00h = default, 01h = A:, etc) - */ -static const char *INT21_DriveName(int drive) -{ - if (drive > 0) return wine_dbg_sprintf( "%c:", 'A' + drive - 1 ); - return "default"; -} - -static HFILE16 _lcreat16_uniq( LPCSTR path, INT attr ) -{ - /* Mask off all flags not explicitly allowed by the doc */ - attr &= FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM; - return Win32HandleToDosFileHandle( CreateFileA( path, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, - CREATE_NEW, attr, 0 )); -} - - static int INT21_FindFirst( CONTEXT86 *context ) { char *p; @@ -392,68 +213,6 @@ return 1; } - -static BOOL INT21_CreateTempFile( CONTEXT86 *context ) -{ - static int counter = 0; - char *name = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx ); - char *p = name + strlen(name); - - /* despite what Ralf Brown says, some programs seem to call without - * ending backslash (DOS accepts that, so we accept it too) */ - if ((p == name) || (p[-1] != '\\')) *p++ = '\\'; - - for (;;) - { - sprintf( p, "wine%04x.%03d", (int)getpid(), counter ); - counter = (counter + 1) % 1000; - - SET_AX( context, _lcreat16_uniq( name, 0 ) ); - if (AX_reg(context) != HFILE_ERROR16) - { - TRACE("created %s\n", name ); - return TRUE; - } - if (GetLastError() != ERROR_FILE_EXISTS) return FALSE; - } -} - - -static int INT21_GetDiskSerialNumber( CONTEXT86 *context ) -{ - BYTE *dataptr = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx); - int drive = DOS_GET_DRIVE( BL_reg(context) ); - - if (!DRIVE_IsValid(drive)) - { - SetLastError( ERROR_INVALID_DRIVE ); - return 0; - } - - *(WORD *)dataptr = 0; - *(DWORD *)(dataptr + 2) = DRIVE_GetSerialNumber( drive ); - memcpy( dataptr + 6, DRIVE_GetLabel( drive ), 11 ); - strncpy(dataptr + 0x11, "FAT16 ", 8); - return 1; -} - - -static int INT21_SetDiskSerialNumber( CONTEXT86 *context ) -{ - BYTE *dataptr = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx); - int drive = DOS_GET_DRIVE( BL_reg(context) ); - - if (!DRIVE_IsValid(drive)) - { - SetLastError( ERROR_INVALID_DRIVE ); - return 0; - } - - DRIVE_SetSerialNumber( drive, *(DWORD *)(dataptr + 2) ); - return 1; -} - - /* microsoft's programmers should be shot for using CP/M style int21 calls in Windows for Workgroup's winfile.exe */ @@ -550,38 +309,6 @@ } -static BOOL -INT21_networkfunc (CONTEXT86 *context) -{ - switch (AL_reg(context)) { - case 0x00: /* Get machine name. */ - { - char *dst = CTX_SEG_OFF_TO_LIN (context,context->SegDs,context->Edx); - TRACE("getting machine name to %p\n", dst); - if (gethostname (dst, 15)) - { - WARN("failed!\n"); - SetLastError( ER_NoNetwork ); - return TRUE; - } else { - int len = strlen (dst); - while (len < 15) - dst[len++] = ' '; - dst[15] = 0; - SET_CH( context, 1 ); /* Valid */ - SET_CL( context, 1 ); /* NETbios number??? */ - TRACE("returning %s\n", debugstr_an (dst, 16)); - return FALSE; - } - } - - default: - SetLastError( ER_NoNetwork ); - return TRUE; - } -} - - /*********************************************************************** * INT_Int21Handler */ @@ -605,50 +332,10 @@ SET_AL( context, INT21_FindNextFCB(context) ? 0x00 : 0xff ); break; - case 0x1b: /* GET ALLOCATION INFORMATION FOR DEFAULT DRIVE */ - SET_DL( context, 0 ); - if (!INT21_GetDriveAllocInfo(context)) SET_AX( context, 0xffff ); - break; - - case 0x1c: /* GET ALLOCATION INFORMATION FOR SPECIFIC DRIVE */ - if (!INT21_GetDriveAllocInfo(context)) SET_AX( context, 0xffff ); - break; - case 0x29: /* PARSE FILENAME INTO FCB */ INT21_ParseFileNameIntoFCB(context); break; - case 0x36: /* GET FREE DISK SPACE */ - TRACE("GET FREE DISK SPACE FOR DRIVE %s\n", - INT21_DriveName( DL_reg(context))); - if (!INT21_GetFreeDiskSpace(context)) SET_AX( context, 0xffff ); - break; - - case 0x44: /* IOCTL */ - switch (AL_reg(context)) - { - case 0x0d: - TRACE("IOCTL - GENERIC BLOCK DEVICE REQUEST %s\n", - INT21_DriveName( BL_reg(context))); - bSetDOSExtendedError = ioctlGenericBlkDevReq(context); - break; - - case 0x0F: /* Set logical drive mapping */ - { - int drive; - TRACE("IOCTL - SET LOGICAL DRIVE MAP for drive %s\n", - INT21_DriveName( BL_reg(context))); - drive = DOS_GET_DRIVE ( BL_reg(context) ); - if ( ! DRIVE_SetLogicalMapping ( drive, drive+1 ) ) - { - SET_CFLAG(context); - SET_AX( context, 0x000F ); /* invalid drive */ - } - break; - } - } - break; - case 0x4e: /* "FINDFIRST" - FIND FIRST MATCHING FILE */ TRACE("FINDFIRST mask 0x%04x spec %s\n",CX_reg(context), (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx)); @@ -666,15 +353,6 @@ else SET_AX( context, 0 ); /* OK */ break; - case 0x5a: /* CREATE TEMPORARY FILE */ - TRACE("CREATE TEMPORARY FILE\n"); - bSetDOSExtendedError = !INT21_CreateTempFile(context); - break; - - case 0x5e: - bSetDOSExtendedError = INT21_networkfunc (context); - break; - case 0x5f: /* NETWORK */ switch (AL_reg(context)) { @@ -696,47 +374,6 @@ } break; - default: - /* network software not installed */ - TRACE("NETWORK function AX=%04x not implemented\n",AX_reg(context)); - SetLastError( ER_NoNetwork ); - bSetDOSExtendedError = TRUE; - break; - } - break; - - case 0x60: /* "TRUENAME" - CANONICALIZE FILENAME OR PATH */ - TRACE("TRUENAME %s\n", - (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs,context->Esi)); - { - if (!GetFullPathNameA( CTX_SEG_OFF_TO_LIN(context, context->SegDs, - context->Esi), 128, - CTX_SEG_OFF_TO_LIN(context, context->SegEs, - context->Edi),NULL)) - bSetDOSExtendedError = TRUE; - else SET_AX( context, 0 ); - } - break; - - case 0x69: /* DISK SERIAL NUMBER */ - switch (AL_reg(context)) - { - case 0x00: - TRACE("GET DISK SERIAL NUMBER for drive %s\n", - INT21_DriveName(BL_reg(context))); - if (!INT21_GetDiskSerialNumber(context)) bSetDOSExtendedError = TRUE; - else SET_AX( context, 0 ); - break; - - case 0x01: - TRACE("SET DISK SERIAL NUMBER for drive %s\n", - INT21_DriveName(BL_reg(context))); - if (!INT21_SetDiskSerialNumber(context)) bSetDOSExtendedError = TRUE; - else SET_AX( context, 1 ); - break; - } - break; - case 0x71: /* MS-DOS 7 (Windows95) - LONG FILENAME FUNCTIONS */ switch(AL_reg(context)) {