ntdll / kernel32: #36
Eric Pouech
pouech-eric at wanadoo.fr
Thu Nov 13 14:26:12 CST 2003
- moved the remaining of int21 calls to dlls/winedos
- disabled drive enabling/disabling as well as disk serial number
writing (for DLL separation issues)
- added volume management prototypes to include/winebase.h
- started DefineDosDevice (needed by first item in this list)
- removed int21 specific code from dlls/kernel32
A+
--
Eric Pouech
-------------- next part --------------
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel35/kernel32.spec dlls/kernel/kernel32.spec
--- dlls/kernel35/kernel32.spec 2003-11-09 19:31:14.000000000 +0100
+++ dlls/kernel/kernel32.spec 2003-11-11 22:34:11.000000000 +0100
@@ -221,7 +221,7 @@
@ stdcall DebugActiveProcess(long)
@ stdcall DebugBreak()
@ stdcall DefineDosDeviceA(long str str)
-@ stub DefineDosDeviceW
+@ stdcall DefineDosDeviceW(long wstr wstr)
@ stub DelayLoadFailureHook
@ stdcall DeleteAtom(long)
@ stdcall DeleteCriticalSection(ptr) ntdll.RtlDeleteCriticalSection
@@ -1150,7 +1150,6 @@
@ cdecl DOSMEM_ResizeBlock(ptr long long)
@ cdecl DRIVE_OpenDevice(long long)
@ cdecl FILE_Dup2(long long)
-@ stdcall INT_Int21Handler(ptr)
@ cdecl LOCAL_Alloc(long long long)
@ cdecl LOCAL_Compact(long long long)
@ cdecl LOCAL_CountFree(long)
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel35/Makefile.in dlls/kernel/Makefile.in
--- dlls/kernel35/Makefile.in 2003-11-12 21:46:50.000000000 +0100
+++ dlls/kernel/Makefile.in 2003-11-12 20:44:18.000000000 +0100
@@ -29,7 +29,6 @@
$(TOPOBJDIR)/misc/options.c \
$(TOPOBJDIR)/misc/registry.c \
$(TOPOBJDIR)/msdos/dpmi.c \
- $(TOPOBJDIR)/msdos/int21.c \
atom.c \
change.c \
comm.c \
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/winedos35/int21.c dlls/winedos/int21.c
--- dlls/winedos35/int21.c 2003-11-11 13:58:09.000000000 +0100
+++ dlls/winedos/int21.c 2003-11-13 21:15:49.000000000 +0100
@@ -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"
@@ -44,9 +48,15 @@
#include "wine/exception.h"
/*
- * FIXME: Delete this reference when all int21 code has been moved to winedos.
+ * Note:
+ * - Most of the file related functions are wrong. NT's kernel32
+ * doesn't maintain a per drive current directory, while DOS does.
+ * We should in fact keep track in here of those per driver
+ * directories, and use this infro while dealing with partial paths
+ * (drive defined, but only relative paths). This could even be
+ * created as an array of CDS (there should be an entry for that in
+ * the LOL)
*/
-extern void WINAPI INT_Int21Handler( CONTEXT86 *context );
/*
* Forward declarations.
@@ -161,13 +171,32 @@
#include "poppack.h"
+/* 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)
+ {
+ if (drive <= 26) return wine_dbg_sprintf("%c:", 'A' + drive - 1);
+ else return wine_dbg_sprintf( "<Bad drive: %d>", drive);
+ }
+ 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 +2121,51 @@
SET_BX( context, DOSVM_psp );
}
+static void CreateBPB(int drive, BYTE *data, BOOL16 limited)
+/* limited == TRUE is used with INT 0x21/0x440d */
+{
+ /* FIXME: we're forcing some values without checking that those are valid */
+ 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 +2250,25 @@
break;
case 0x0860: /* get device parameters */
- INT_Int21Handler( context );
+ /* FIXME: we're faking some values here */
+ /* 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 +2290,17 @@
break;
case 0x0866: /* get volume serial number */
- INT_Int21Handler( context );
+ {
+ WCHAR label[12],fsname[9];
+ DWORD serial;
+
+ drivespec[0] += drive;
+ GetVolumeInformationW(drivespec, label, 12, &serial, NULL, NULL, fsname, 9);
+ *(WORD*)dataptr = 0;
+ memcpy(dataptr+2,&serial,4);
+ WideCharToMultiByte(CP_OEMCP, 0, label, 11, dataptr + 6, 11, NULL, NULL);
+ WideCharToMultiByte(CP_OEMCP, 0, fsname, 8, dataptr + 17, 8, NULL, NULL);
+ }
break;
case 0x086a: /* unlock logical volume */
@@ -2207,11 +2309,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 +2334,19 @@
break;
case 0x0f: /* SET LOGICAL DRIVE MAP */
- INT_Int21Handler( context );
+ {
+ WCHAR dev[3], tgt[4];
+
+ TRACE("IOCTL - SET LOGICAL DRIVE MAP for drive %s\n",
+ INT21_DriveName( BL_reg(context)));
+ dev[0] = 'A' + drive; dev[1] = ':'; dev[2] = 0;
+ tgt[0] = 'A' + drive + 1; dev[1] = ':'; dev[2] = '\\'; dev[3] = 0;
+ if (!DefineDosDeviceW(DDD_RAW_TARGET_PATH, dev, tgt))
+ {
+ SET_CFLAG(context);
+ SET_AX( context, 0x000F ); /* invalid drive */
+ }
+ }
break;
case 0x11: /* QUERY GENERIC IOCTL CAPABILITY */
@@ -2530,6 +2654,20 @@
return TRUE;
}
+static void INT21_ConvertFindDataAtoW(WIN32_FIND_DATAA *dataA,
+ const WIN32_FIND_DATAW *dataW)
+{
+ dataA->dwFileAttributes = dataW->dwFileAttributes;
+ dataA->ftCreationTime = dataW->ftCreationTime;
+ dataA->ftLastAccessTime = dataW->ftLastAccessTime;
+ dataA->ftLastWriteTime = dataW->ftLastWriteTime;
+ dataA->nFileSizeHigh = dataW->nFileSizeHigh;
+ dataA->nFileSizeLow = dataW->nFileSizeLow;
+ WideCharToMultiByte( CP_OEMCP, 0, dataW->cFileName, -1,
+ dataA->cFileName, sizeof(dataA->cFileName), NULL, NULL );
+ WideCharToMultiByte( CP_OEMCP, 0, dataW->cAlternateFileName, -1,
+ dataA->cAlternateFileName, sizeof(dataA->cAlternateFileName), NULL, NULL );
+}
/***********************************************************************
* INT21_LongFilename
@@ -2539,6 +2677,8 @@
static void INT21_LongFilename( CONTEXT86 *context )
{
BOOL bSetDOSExtendedError = FALSE;
+ WCHAR pathW[MAX_PATH];
+ char* pathA;
if (HIBYTE(HIWORD(GetVersion16())) < 0x07)
{
@@ -2560,17 +2700,11 @@
break;
case 0x3a: /* LONG FILENAME - REMOVE DIRECTORY */
- {
- WCHAR dirW[MAX_PATH];
- char *dirA = CTX_SEG_OFF_TO_LIN(context,
- context->SegDs, context->Edx);
+ pathA = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
- TRACE( "LONG FILENAME - REMOVE DIRECTORY %s\n", dirA );
- MultiByteToWideChar(CP_OEMCP, 0, dirA, -1, dirW, MAX_PATH);
-
- if (!RemoveDirectoryW( dirW ))
- bSetDOSExtendedError = TRUE;
- }
+ TRACE( "LONG FILENAME - REMOVE DIRECTORY %s\n", pathA);
+ MultiByteToWideChar(CP_OEMCP, 0, pathA, -1, pathW, MAX_PATH);
+ if (!RemoveDirectoryW( pathW )) bSetDOSExtendedError = TRUE;
break;
case 0x3b: /* LONG FILENAME - CHANGE DIRECTORY */
@@ -2579,17 +2713,12 @@
break;
case 0x41: /* LONG FILENAME - DELETE FILE */
- {
- WCHAR fileW[MAX_PATH];
- char *fileA = CTX_SEG_OFF_TO_LIN(context,
- context->SegDs, context->Edx);
+ pathA = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
- TRACE( "LONG FILENAME - DELETE FILE %s\n", fileA );
- MultiByteToWideChar(CP_OEMCP, 0, fileA, -1, fileW, MAX_PATH);
+ TRACE( "LONG FILENAME - DELETE FILE %s\n", pathA );
+ MultiByteToWideChar(CP_OEMCP, 0, pathA, -1, pathW, MAX_PATH);
- if (!DeleteFileW( fileW ))
- bSetDOSExtendedError = TRUE;
- }
+ if (!DeleteFileW( pathW )) bSetDOSExtendedError = TRUE;
break;
case 0x43: /* LONG FILENAME - EXTENDED GET/SET FILE ATTRIBUTES */
@@ -2603,8 +2732,63 @@
break;
case 0x4e: /* LONG FILENAME - FIND FIRST MATCHING FILE */
+ {
+ HANDLE handle;
+ HGLOBAL16 h16;
+ WIN32_FIND_DATAW dataW;
+ WIN32_FIND_DATAA* dataA;
+
+ pathA = CTX_SEG_OFF_TO_LIN(context, context->SegDs,context->Edx);
+ TRACE(" LONG FILENAME - FIND FIRST MATCHING FILE for %s\n", pathA);
+
+ MultiByteToWideChar(CP_OEMCP, 0, pathA, -1, pathW, MAX_PATH);
+ handle = FindFirstFileW(pathW, &dataW);
+
+ dataA = (WIN32_FIND_DATAA *)CTX_SEG_OFF_TO_LIN(context, context->SegEs,
+ context->Edi);
+ if (handle != INVALID_HANDLE_VALUE &&
+ (h16 = GlobalAlloc16(GMEM_MOVEABLE, sizeof(handle))))
+ {
+ HANDLE* ptr = GlobalLock16( h16 );
+ *ptr = handle;
+ GlobalUnlock16( h16 );
+ SET_AX( context, h16 );
+ INT21_ConvertFindDataAtoW(dataA, &dataW);
+ }
+ else
+ {
+ if (handle != INVALID_HANDLE_VALUE) FindClose(handle);
+ SET_AX( context, INVALID_HANDLE_VALUE16);
+ bSetDOSExtendedError = TRUE;
+ }
+ }
+ break;
+
case 0x4f: /* LONG FILENAME - FIND NEXT MATCHING FILE */
- INT_Int21Handler( context );
+ {
+ HGLOBAL16 h16 = BX_reg(context);
+ HANDLE* ptr;
+ WIN32_FIND_DATAW dataW;
+ WIN32_FIND_DATAA* dataA;
+
+ TRACE("LONG FILENAME - FIND NEXT MATCHING FILE for handle %d\n",
+ BX_reg(context));
+
+ dataA = (WIN32_FIND_DATAA *)CTX_SEG_OFF_TO_LIN(context, context->SegEs,
+ context->Edi);
+
+ if (h16 != INVALID_HANDLE_VALUE16 && (ptr = GlobalLock16( h16 )))
+ {
+ if (!FindNextFileW(*ptr, &dataW)) bSetDOSExtendedError = TRUE;
+ else INT21_ConvertFindDataAtoW(dataA, &dataW);
+ GlobalUnlock16( h16 );
+ }
+ else
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ bSetDOSExtendedError = TRUE;
+ }
+ }
break;
case 0x56: /* LONG FILENAME - RENAME FILE */
@@ -2613,7 +2797,44 @@
break;
case 0x60: /* LONG FILENAME - CONVERT PATH */
- INT_Int21Handler( context );
+ {
+ WCHAR res[MAX_PATH];
+
+ switch (CL_reg(context))
+ {
+ case 0x01: /* Get short filename or path */
+ MultiByteToWideChar(CP_OEMCP, 0, CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Esi), -1, pathW, MAX_PATH);
+ if (!GetShortPathNameW(pathW, res, 67))
+ bSetDOSExtendedError = TRUE;
+ else
+ {
+ SET_AX( context, 0 );
+ WideCharToMultiByte(CP_OEMCP, 0, res, -1,
+ CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edi),
+ 67, NULL, NULL);
+ }
+ break;
+
+ case 0x02: /* Get canonical long filename or path */
+ MultiByteToWideChar(CP_OEMCP, 0, CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Esi), -1, pathW, MAX_PATH);
+ if (!GetFullPathNameW(pathW, 128, res, NULL))
+ bSetDOSExtendedError = TRUE;
+ else
+ {
+ SET_AX( context, 0 );
+ WideCharToMultiByte(CP_OEMCP, 0, res, -1,
+ CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edi),
+ 128, NULL, NULL);
+ }
+ break;
+ default:
+ FIXME("Unimplemented long file name function:\n");
+ INT_BARF( context, 0x21 );
+ SET_CFLAG(context);
+ SET_AL( context, 0 );
+ break;
+ }
+ }
break;
case 0x6c: /* LONG FILENAME - CREATE OR OPEN FILE */
@@ -2623,10 +2844,52 @@
break;
case 0xa0: /* LONG FILENAME - GET VOLUME INFORMATION */
- case 0xa1: /* LONG FILENAME - "FindClose" - TERMINATE DIRECTORY SEARCH */
- INT_Int21Handler( context );
+ {
+ DWORD filename_len, flags;
+ WCHAR dstW[8];
+
+ pathA = CTX_SEG_OFF_TO_LIN(context, context->SegDs,context->Edx);
+
+ TRACE("LONG FILENAME - GET VOLUME INFORMATION for drive having root dir '%s'.\n", pathA);
+ SET_AX( context, 0 );
+ MultiByteToWideChar(CP_OEMCP, 0, pathA, -1, pathW, MAX_PATH);
+ if (!GetVolumeInformationW( pathW, NULL, 0, NULL, &filename_len,
+ &flags, dstW, 8 ))
+ {
+ INT_BARF( context, 0x21 );
+ SET_CFLAG(context);
+ break;
+ }
+ SET_BX( context, flags | 0x4000 ); /* support for LFN functions */
+ SET_CX( context, filename_len );
+ SET_DX( context, MAX_PATH ); /* FIXME: which len if DRIVE_SHORT_NAMES ? */
+ WideCharToMultiByte(CP_OEMCP, 0, dstW, -1,
+ CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edi),
+ 8, NULL, NULL);
+ }
break;
+ case 0xa1: /* LONG FILENAME - "FindClose" - TERMINATE DIRECTORY SEARCH */
+ {
+ HGLOBAL16 h16 = BX_reg(context);
+ HANDLE* ptr;
+
+ TRACE("LONG FILENAME - FINDCLOSE for handle %d\n",
+ BX_reg(context));
+ if (h16 != INVALID_HANDLE_VALUE16 && (ptr = GlobalLock16( h16 )))
+ {
+ if (!FindClose( *ptr )) bSetDOSExtendedError = TRUE;
+ GlobalUnlock16( h16 );
+ GlobalFree16( h16 );
+ }
+ else
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ bSetDOSExtendedError = TRUE;
+ }
+ }
+ break;
+
case 0xa6: /* LONG FILENAME - GET FILE INFO BY HANDLE */
{
HANDLE handle = DosFileHandleToWin32Handle(BX_reg(context));
@@ -2692,7 +2955,11 @@
case 0xa9: /* LONG FILENAME - SERVER CREATE OR OPEN FILE */
case 0xaa: /* LONG FILENAME - SUBST */
default:
+ FIXME("Unimplemented long file name function:\n");
INT_BARF( context, 0x21 );
+ SET_CFLAG(context);
+ SET_AL( context, 0 );
+ break;
}
if (bSetDOSExtendedError)
@@ -2729,6 +2996,134 @@
/***********************************************************************
+ * INT21_NetworkFunc
+ *
+ * Handler for:
+ * - function 0x5e
+ */
+static BOOL INT21_NetworkFunc (CONTEXT86 *context)
+{
+ switch (AL_reg(context))
+ {
+ case 0x00: /* Get machine name. */
+ {
+ WCHAR dstW[MAX_COMPUTERNAME_LENGTH + 1];
+ DWORD s = sizeof(dstW) / sizeof(WCHAR);
+ int len;
+
+ char *dst = CTX_SEG_OFF_TO_LIN (context,context->SegDs,context->Edx);
+ TRACE("getting machine name to %p\n", dst);
+ if (!GetComputerNameW(dstW, &s) ||
+ !WideCharToMultiByte(CP_OEMCP, 0, dstW, -1, dst, 16, NULL, NULL))
+ {
+ WARN("failed!\n");
+ SetLastError( ER_NoNetwork );
+ return TRUE;
+ }
+ for (len = strlen(dst); len < 15; len++) 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);
+ WCHAR path[] = {'A',':',0}, label[11];
+ DWORD serial;
+
+ path[0] += INT21_MapDrive(BL_reg(context));
+ if (!GetVolumeInformationW( path, label, 11, &serial, NULL, NULL, NULL, 0))
+ {
+ SetLastError( ERROR_INVALID_DRIVE );
+ return 0;
+ }
+
+ *(WORD *)dataptr = 0;
+ memcpy(dataptr + 2, &serial, sizeof(DWORD));
+ WideCharToMultiByte(CP_OEMCP, 0, label, 11, dataptr + 6, 11, NULL, NULL);
+ strncpy(dataptr + 17, "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 = INT21_MapDrive(BL_reg(context));
+
+ 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;
+ WCHAR root[] = {'A',':','\\',0};
+
+ root[0] += INT21_MapDrive(BL_reg(context));
+ if (!GetDiskFreeSpaceW( 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, int drive )
+{
+ INT21_DPB *dpb;
+
+ if (!INT21_FillDrivePB( drive )) return 0;
+ dpb = &(INT21_GetHeapPointer()->misc_dpb_list[drive]);
+ SET_AL( context, dpb->cluster_sectors + 1 );
+ SET_CX( context, dpb->sector_bytes );
+ SET_DX( context, dpb->num_clusters1 );
+
+ context->SegDs = INT21_GetHeapSelector( context );
+ SET_BX( context, offsetof( INT21_HEAP, misc_dpb_list[drive].media_ID ) );
+ return 1;
+}
+
+/***********************************************************************
* INT21_GetExtendedError
*/
static void INT21_GetExtendedError( CONTEXT86 *context )
@@ -2843,6 +3238,452 @@
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;
+ }
+}
+
+/***********************************************************************
+ * DOSFS_ToDosFCBFormat
+ *
+ * Convert a file name to DOS FCB format (8+3 chars, padded with blanks),
+ * expanding wild cards and converting to upper-case in the process.
+ * File name can be terminated by '\0', '\\' or '/'.
+ * Return FALSE if the name is not a valid DOS name.
+ * 'buffer' must be at least 12 characters long.
+ */
+/* Chars we don't want to see in DOS file names */
+#define INVALID_DOS_CHARS "*?<>|\"+=,;[] \345"
+static BOOL INT21_ToDosFCBFormat( LPCWSTR name, LPWSTR buffer )
+{
+ static const char invalid_chars[] = INVALID_DOS_CHARS;
+ LPCWSTR p = name;
+ int i;
+
+ /* Check for "." and ".." */
+ if (*p == '.')
+ {
+ p++;
+ buffer[0] = '.';
+ for(i = 1; i < 11; i++) buffer[i] = ' ';
+ buffer[11] = 0;
+ if (*p == '.')
+ {
+ buffer[1] = '.';
+ p++;
+ }
+ return (!*p || (*p == '/') || (*p == '\\'));
+ }
+
+ for (i = 0; i < 8; i++)
+ {
+ switch(*p)
+ {
+ case '\0':
+ case '\\':
+ case '/':
+ case '.':
+ buffer[i] = ' ';
+ break;
+ case '?':
+ p++;
+ /* fall through */
+ case '*':
+ buffer[i] = '?';
+ break;
+ default:
+ if (*p < 256 && strchr( invalid_chars, (char)*p )) return FALSE;
+ buffer[i] = toupperW(*p);
+ p++;
+ break;
+ }
+ }
+
+ if (*p == '*')
+ {
+ /* Skip all chars after wildcard up to first dot */
+ while (*p && (*p != '/') && (*p != '\\') && (*p != '.')) p++;
+ }
+ else
+ {
+ /* Check if name too long */
+ if (*p && (*p != '/') && (*p != '\\') && (*p != '.')) return FALSE;
+ }
+ if (*p == '.') p++; /* Skip dot */
+
+ for (i = 8; i < 11; i++)
+ {
+ switch(*p)
+ {
+ case '\0':
+ case '\\':
+ case '/':
+ buffer[i] = ' ';
+ break;
+ case '.':
+ return FALSE; /* Second extension not allowed */
+ case '?':
+ p++;
+ /* fall through */
+ case '*':
+ buffer[i] = '?';
+ break;
+ default:
+ if (*p < 256 && strchr( invalid_chars, (char)*p )) return FALSE;
+ buffer[i] = toupperW(*p);
+ p++;
+ break;
+ }
+ }
+ buffer[11] = '\0';
+
+ /* at most 3 character of the extension are processed
+ * is something behind this ?
+ */
+ while (*p == '*' || *p == ' ') p++; /* skip wildcards and spaces */
+ return IS_END_OF_NAME(*p);
+}
+
+static HANDLE INT21_FindHandle;
+static const void* INT21_FindPath; /* will point to current dta->fullPath search */
+/******************************************************************
+ * INT21_FindFirst
+ */
+static int INT21_FindFirst( CONTEXT86 *context )
+{
+ WCHAR *p;
+ const char *path;
+ FINDFILE_DTA *dta = (FINDFILE_DTA *)INT21_GetCurrentDTA(context);
+ WCHAR maskW[12], pathW[MAX_PATH];
+ DWORD attr;
+
+ path = (const char *)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
+ MultiByteToWideChar(CP_OEMCP, 0, path, -1, pathW, MAX_PATH);
+
+ dta->fullPath = HeapAlloc( GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) );
+ p = strrchrW(pathW, '/');
+ if (p) *p = '\0';
+ GetLongPathNameW(pathW, dta->fullPath, MAX_PATH);
+ if (p) *p = '/';
+ attr = GetFileAttributesW(dta->fullPath);
+ if (attr == 0xffffffff || !(attr & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ SET_AX( context, GetLastError() );
+ SET_CFLAG(context);
+ return 0;
+ }
+
+ /* Note: terminating NULL in dta->mask overwrites dta->search_attr
+ * (doesn't matter as it is set below anyway)
+ */
+ if (!INT21_ToDosFCBFormat( p, maskW ))
+ {
+ HeapFree( GetProcessHeap(), 0, dta->fullPath );
+ dta->fullPath = NULL;
+ SetLastError( ERROR_FILE_NOT_FOUND );
+ SET_AX( context, ERROR_FILE_NOT_FOUND );
+ SET_CFLAG(context);
+ return 0;
+ }
+ WideCharToMultiByte(CP_OEMCP, 0, maskW, 12, dta->mask, sizeof(dta->mask), NULL, NULL);
+ /* we must have a fully qualified file name in dta->fullPath
+ * (we could have a UNC path, but this would lead to some errors later on)
+ */
+ dta->drive = toupperW(((WCHAR*)dta->fullPath)[0]) - 'A';
+ dta->count = 0;
+ dta->search_attr = CL_reg(context);
+ return 1;
+}
+
+/******************************************************************
+ * match_short
+ *
+ * Check is a short path name (DTA unicode) matches a mask (FCB ansi)
+ */
+static BOOL match_short(LPCWSTR shortW, LPCSTR maskA)
+{
+ WCHAR mask[12];
+ int i, j;
+
+ MultiByteToWideChar(CP_OEMCP, 0, maskA, 12, mask, 12);
+
+ for (i = j = 0; i < 8; i++)
+ {
+ switch (mask[i])
+ {
+ case '?':
+ if (shortW[j] == '\0' || shortW[j] == '.') return FALSE;
+ j++;
+ break;
+ case ' ': if (shortW[j] != '.') return FALSE; break;
+ default: if (shortW[j++] != mask[i]) return FALSE; break;
+ }
+ }
+ for (i = 8; i < 11; i++)
+ {
+ switch (mask[i])
+ {
+ case '?': if (shortW[j++] == '\0') return FALSE; break;
+ case ' ': if (shortW[j] != '\0') return FALSE; break;
+ default: if (shortW[j++] != mask[i]) return FALSE; break;
+ }
+ }
+ return TRUE;
+}
+
+static unsigned INT21_FindHelper(LPCWSTR fullPath, unsigned drive, unsigned count,
+ LPCSTR mask, unsigned search_attr,
+ WIN32_FIND_DATAW* entry)
+{
+ unsigned ncalls;
+
+ if ((search_attr & ~(FA_UNUSED | FA_ARCHIVE | FA_RDONLY)) == FA_LABEL)
+ {
+ WCHAR path[] = {' ',':',0};
+
+ if (count) return 0;
+ path[0] = drive + 'A';
+ if (!GetVolumeInformationW(path, entry->cAlternateFileName, 13, NULL, NULL, NULL, NULL, 0)) return 0;
+ RtlSecondsSince1970ToTime( (time_t)0, (LARGE_INTEGER *)&entry->ftCreationTime );
+ RtlSecondsSince1970ToTime( (time_t)0, (LARGE_INTEGER *)&entry->ftLastAccessTime );
+ RtlSecondsSince1970ToTime( (time_t)0, (LARGE_INTEGER *)&entry->ftLastWriteTime );
+ entry->dwFileAttributes = FILE_ATTRIBUTE_LABEL;
+ entry->nFileSizeHigh = entry->nFileSizeLow = 0;
+ TRACE("returning %s as label\n", debugstr_w(entry->cAlternateFileName));
+ return 1;
+ }
+
+
+ if (!INT21_FindHandle || INT21_FindPath != fullPath || count == 0)
+ {
+ if (INT21_FindHandle) FindClose(INT21_FindHandle);
+ INT21_FindHandle = FindFirstFileW(fullPath, entry);
+ if (INT21_FindHandle == INVALID_HANDLE_VALUE)
+ {
+ INT21_FindHandle = 0;
+ return 0;
+ }
+ INT21_FindPath = fullPath;
+ /* we need to resync search */
+ ncalls = count;
+ }
+ else ncalls = 1;
+
+ while (ncalls-- != 0)
+ {
+ if (!FindNextFileW(INT21_FindHandle, entry))
+ {
+ FindClose(INT21_FindHandle); INT21_FindHandle = 0;
+ return 0;
+ }
+ }
+ while (count < 0xffff)
+ {
+ count++;
+ /* Check the file attributes, and path */
+ if (!(entry->dwFileAttributes & ~search_attr) &&
+ match_short(entry->cAlternateFileName, mask))
+ {
+ return count;
+ }
+ if (!FindNextFileW(INT21_FindHandle, entry))
+ {
+ FindClose(INT21_FindHandle); INT21_FindHandle = 0;
+ return 0;
+ }
+ }
+ WARN("Too many directory entries in %s\n", debugstr_w(fullPath) );
+ return 0;
+}
+
+/******************************************************************
+ * INT21_FindNext
+ */
+static int INT21_FindNext( CONTEXT86 *context )
+{
+ FINDFILE_DTA *dta = (FINDFILE_DTA *)INT21_GetCurrentDTA(context);
+ DWORD attr = dta->search_attr | FA_UNUSED | FA_ARCHIVE | FA_RDONLY;
+ WIN32_FIND_DATAW entry;
+ int n;
+
+ if (!dta->fullPath) return 0;
+
+ n = INT21_FindHelper(dta->fullPath, dta->drive, dta->count,
+ dta->mask, attr, &entry);
+ if (n)
+ {
+ dta->fileattr = entry.dwFileAttributes;
+ dta->filesize = entry.nFileSizeLow;
+ FileTimeToDosDateTime( &entry.ftLastWriteTime, &dta->filedate, &dta->filetime );
+ WideCharToMultiByte(CP_OEMCP, 0, entry.cAlternateFileName, -1,
+ dta->filename, 13, NULL, NULL);
+ if (!memchr(dta->mask,'?',11))
+ {
+ /* wildcardless search, release resources in case no findnext will
+ * be issued, and as a workaround in case file creation messes up
+ * findnext, as sometimes happens with pkunzip
+ */
+ HeapFree( GetProcessHeap(), 0, dta->fullPath );
+ INT21_FindPath = dta->fullPath = NULL;
+ }
+ dta->count += n;
+ return 1;
+ }
+ HeapFree( GetProcessHeap(), 0, dta->fullPath );
+ INT21_FindPath = dta->fullPath = NULL;
+ return 0;
+}
+
+/* microsoft's programmers should be shot for using CP/M style int21
+ calls in Windows for Workgroup's winfile.exe */
+
+/******************************************************************
+ * INT21_FindFirstFCB
+ *
+ */
+static int INT21_FindFirstFCB( CONTEXT86 *context )
+{
+ BYTE *fcb = (BYTE *)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
+ FINDFILE_FCB *pFCB;
+ int drive;
+ WCHAR p[] = {' ',':',};
+
+ if (*fcb == 0xff) pFCB = (FINDFILE_FCB *)(fcb + 7);
+ else pFCB = (FINDFILE_FCB *)fcb;
+ drive = INT21_MapDrive( pFCB->drive );
+ if (drive == MAX_DOS_DRIVES) return 0;
+
+ p[0] = 'A' + drive;
+ pFCB->fullPath = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
+ if (!pFCB->fullPath) return 0;
+ GetLongPathNameW(p, pFCB->fullPath, MAX_PATH);
+ pFCB->count = 0;
+ return 1;
+}
+
+/******************************************************************
+ * INT21_FindNextFCB
+ *
+ */
+static int INT21_FindNextFCB( CONTEXT86 *context )
+{
+ BYTE *fcb = (BYTE *)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
+ FINDFILE_FCB *pFCB;
+ DOS_DIRENTRY_LAYOUT *pResult = (DOS_DIRENTRY_LAYOUT *)INT21_GetCurrentDTA(context);
+ WIN32_FIND_DATAW entry;
+ BYTE attr;
+ int n;
+ WCHAR nameW[12];
+
+ if (*fcb == 0xff) /* extended FCB ? */
+ {
+ attr = fcb[6];
+ pFCB = (FINDFILE_FCB *)(fcb + 7);
+ }
+ else
+ {
+ attr = 0;
+ pFCB = (FINDFILE_FCB *)fcb;
+ }
+
+ if (!pFCB->fullPath) return 0;
+ n = INT21_FindHelper(pFCB->fullPath, INT21_MapDrive( pFCB->drive ),
+ pFCB->count, pFCB->filename, attr, &entry);
+ if (!n)
+ {
+ HeapFree( GetProcessHeap(), 0, pFCB->fullPath );
+ INT21_FindPath = pFCB->fullPath = NULL;
+ return 0;
+ }
+ pFCB->count += n;
+
+ if (*fcb == 0xff)
+ {
+ /* place extended FCB header before pResult if called with extended FCB */
+ *(BYTE *)pResult = 0xff;
+ (BYTE *)pResult +=6; /* leave reserved field behind */
+ *(BYTE *)pResult = entry.dwFileAttributes;
+ ((BYTE *)pResult)++;
+ }
+ *(BYTE *)pResult = INT21_MapDrive( pFCB->drive ); /* DOS_DIRENTRY_LAYOUT after current drive number */
+ ((BYTE *)pResult)++;
+ pResult->fileattr = entry.dwFileAttributes;
+ pResult->cluster = 0; /* what else? */
+ pResult->filesize = entry.nFileSizeLow;
+ memset( pResult->reserved, 0, sizeof(pResult->reserved) );
+ FileTimeToDosDateTime( &entry.ftLastWriteTime,
+ &pResult->filedate, &pResult->filetime );
+
+ /* Convert file name to FCB format */
+ INT21_ToDosFCBFormat( entry.cAlternateFileName, nameW );
+ WideCharToMultiByte(CP_OEMCP, 0, nameW, 11, pResult->filename, 11, NULL, NULL);
+ return 1;
+}
+
+
+/******************************************************************
+ * INT21_ParseFileNameIntoFCB
+ *
+ */
+static void INT21_ParseFileNameIntoFCB( CONTEXT86 *context )
+{
+ char *filename =
+ CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Esi );
+ char *fcb =
+ CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edi );
+ char *s;
+ WCHAR *buffer;
+ WCHAR fcbW[12];
+ INT buffer_len, len;
+
+ SET_AL( context, 0xff ); /* failed */
+
+ TRACE("filename: '%s'\n", filename);
+
+ s = filename;
+ while (*s && (*s != ' ') && (*s != '\r') && (*s != '\n'))
+ s++;
+ len = filename - s;
+
+ buffer_len = MultiByteToWideChar(CP_OEMCP, 0, filename, len, NULL, 0);
+ buffer = HeapAlloc( GetProcessHeap(), 0, (buffer_len + 1) * sizeof(WCHAR));
+ len = MultiByteToWideChar(CP_OEMCP, 0, filename, len, buffer, buffer_len);
+ buffer[len] = 0;
+ INT21_ToDosFCBFormat(buffer, fcbW);
+ HeapFree(GetProcessHeap(), 0, buffer);
+ WideCharToMultiByte(CP_OEMCP, 0, fcbW, 12, fcb + 1, 12, NULL, NULL);
+ *fcb = 0;
+ TRACE("FCB: '%s'\n", fcb + 1);
+
+ SET_AL( context, ((strchr(filename, '*')) || (strchr(filename, '$'))) != 0 );
+
+ /* point DS:SI to first unparsed character */
+ SET_SI( context, context->Esi + (int)s - (int)filename );
+}
/***********************************************************************
* DOSVM_Int21Handler
@@ -3061,11 +3902,20 @@
break;
case 0x11: /* FIND FIRST MATCHING FILE USING FCB */
+ TRACE("FIND FIRST MATCHING FILE USING FCB %p\n",
+ CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx));
+ if (!INT21_FindFirstFCB(context))
+ {
+ SET_AL( context, 0xff );
+ break;
+ }
+ /* else fall through */
+
case 0x12: /* FIND NEXT MATCHING FILE USING FCB */
- INT_Int21Handler( context );
+ SET_AL( context, INT21_FindNextFCB(context) ? 0x00 : 0xff );
break;
- case 0x13: /* DELETE FILE USING FCB */
+ case 0x13: /* DELETE FILE USING FCB */
INT_BARF( context, 0x21 );
break;
@@ -3101,8 +3951,13 @@
break;
case 0x1b: /* GET ALLOCATION INFORMATION FOR DEFAULT DRIVE */
+ if (!INT21_GetDriveAllocInfo(context, 0))
+ SET_AX( context, 0xffff );
+ break;
+
case 0x1c: /* GET ALLOCATION INFORMATION FOR SPECIFIC DRIVE */
- INT_Int21Handler( context );
+ if (!INT21_GetDriveAllocInfo(context, DL_reg(context)))
+ SET_AX( context, 0xffff );
break;
case 0x1d: /* NULL FUNCTION FOR CP/M COMPATIBILITY */
@@ -3169,7 +4024,7 @@
break;
case 0x29: /* PARSE FILENAME INTO FCB */
- INT_Int21Handler( context );
+ INT21_ParseFileNameIntoFCB(context);
break;
case 0x2a: /* GET SYSTEM DATE */
@@ -3356,7 +4211,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 */
@@ -3608,6 +4465,7 @@
case 0x46: /* "DUP2", "FORCEDUP" - FORCE DUPLICATE FILE HANDLE */
TRACE( "FORCEDUP - FORCE DUPLICATE FILE HANDLE %d to %d\n",
BX_reg(context), CX_reg(context) );
+
if (FILE_Dup2( BX_reg(context), CX_reg(context) ) == HFILE_ERROR16)
bSetDOSExtendedError = TRUE;
else
@@ -3754,8 +4612,20 @@
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));
+ if (!INT21_FindFirst(context)) break;
+ /* fall through */
+
case 0x4f: /* "FINDNEXT" - FIND NEXT MATCHING FILE */
- INT_Int21Handler( context );
+ TRACE("FINDNEXT\n");
+ if (!INT21_FindNext(context))
+ {
+ SetLastError( ERROR_NO_MORE_FILES );
+ SET_AX( context, ERROR_NO_MORE_FILES );
+ SET_CFLAG(context);
+ }
+ else SET_AX( context, 0 ); /* OK */
break;
case 0x50: /* SET CURRENT PROCESS ID (SET PSP ADDRESS) */
@@ -3834,7 +4704,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,9 +4752,38 @@
break;
case 0x5e: /* NETWORK 5E */
+ bSetDOSExtendedError = INT21_NetworkFunc( context);
+ break;
+
case 0x5f: /* NETWORK 5F */
+ /* FIXME: supporting this would need to 1:
+ * - implement per drive current directory (as kernel32 doesn't)
+ * - assign enabled/disabled flag on a per drive basis
+ */
+ /* network software not installed */
+ TRACE("NETWORK function AX=%04x not implemented\n",AX_reg(context));
+ SetLastError( ER_NoNetwork );
+ bSetDOSExtendedError = TRUE;
+ break;
+
case 0x60: /* "TRUENAME" - CANONICALIZE FILENAME OR PATH */
- INT_Int21Handler( context );
+ {
+ WCHAR pathW[MAX_PATH], res[MAX_PATH];
+ /* FIXME: likely to be broken */
+
+ TRACE("TRUENAME %s\n",
+ (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs,context->Esi));
+ MultiByteToWideChar(CP_OEMCP, 0, CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Esi), -1, pathW, MAX_PATH);
+ if (!GetFullPathNameW( pathW, 128, res, NULL ))
+ bSetDOSExtendedError = TRUE;
+ else
+ {
+ SET_AX( context, 0 );
+ WideCharToMultiByte(CP_OEMCP, 0, res, -1,
+ CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edi),
+ 128, NULL, NULL);
+ }
+ }
break;
case 0x61: /* UNUSED */
@@ -3942,7 +4842,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 */
diff -u -N -r -x '*~' -x '.#*' -x CVS files35/dos_fs.c files/dos_fs.c
--- files35/dos_fs.c 2003-11-09 19:31:34.000000000 +0100
+++ files/dos_fs.c 2003-11-11 22:26:10.000000000 +0100
@@ -143,8 +143,6 @@
{
char *path; /* unix path */
LPWSTR long_mask;
- LPWSTR short_mask;
- BYTE attr;
int drive;
int cur_pos;
CRITICAL_SECTION cs;
@@ -333,20 +331,6 @@
/***********************************************************************
- * DOSFS_MatchShort
- *
- * Check a DOS file name against a mask (both in FCB format).
- */
-static int DOSFS_MatchShort( LPCWSTR mask, LPCWSTR name )
-{
- int i;
- for (i = 11; i > 0; i--, mask++, name++)
- if ((*mask != '?') && (*mask != *name)) return 0;
- return 1;
-}
-
-
-/***********************************************************************
* DOSFS_MatchLong
*
* Check a long file name against a mask.
@@ -1777,35 +1761,14 @@
*/
static int DOSFS_FindNextEx( FIND_FIRST_INFO *info, WIN32_FIND_DATAW *entry )
{
- DWORD attr = info->attr | FA_UNUSED | FA_ARCHIVE | FA_RDONLY;
UINT flags = DRIVE_GetFlags( info->drive );
char *p, buffer[MAX_PATHNAME_LEN];
const char *drive_path;
int drive_root;
LPCWSTR long_name, short_name;
BY_HANDLE_FILE_INFORMATION fileinfo;
- WCHAR dos_name[13];
BOOL is_symlink;
- if ((info->attr & ~(FA_UNUSED | FA_ARCHIVE | FA_RDONLY)) == FA_LABEL)
- {
- if (info->cur_pos) return 0;
- entry->dwFileAttributes = FILE_ATTRIBUTE_LABEL;
- RtlSecondsSince1970ToTime( (time_t)0, (LARGE_INTEGER *)&entry->ftCreationTime );
- RtlSecondsSince1970ToTime( (time_t)0, (LARGE_INTEGER *)&entry->ftLastAccessTime );
- RtlSecondsSince1970ToTime( (time_t)0, (LARGE_INTEGER *)&entry->ftLastWriteTime );
- entry->nFileSizeHigh = 0;
- entry->nFileSizeLow = 0;
- entry->dwReserved0 = 0;
- entry->dwReserved1 = 0;
- DOSFS_ToDosDTAFormat( DRIVE_GetLabel( info->drive ), entry->cFileName );
- strcpyW( entry->cAlternateFileName, entry->cFileName );
- info->cur_pos++;
- TRACE("returning %s (%s) as label\n",
- debugstr_w(entry->cFileName), debugstr_w(entry->cAlternateFileName));
- return 1;
- }
-
drive_path = info->path + strlen(DRIVE_GetRoot( info->drive ));
while ((*drive_path == '/') || (*drive_path == '\\')) drive_path++;
drive_root = !*drive_path;
@@ -1831,19 +1794,6 @@
flags & DRIVE_CASE_SENSITIVE )) continue;
}
- /* Check the short mask */
-
- if (info->short_mask)
- {
- if (!short_name)
- {
- DOSFS_Hash( long_name, dos_name, TRUE,
- !(flags & DRIVE_CASE_SENSITIVE) );
- short_name = dos_name;
- }
- if (!DOSFS_MatchShort( info->short_mask, short_name )) continue;
- }
-
/* Check the file attributes */
WideCharToMultiByte(CP_UNIXCP, 0, long_name, -1,
p, sizeof(buffer) - (int)(p - buffer), NULL, NULL);
@@ -1860,8 +1810,6 @@
if (!show_dir_symlinks) continue;
}
- if (fileinfo.dwFileAttributes & ~attr) continue;
-
/* We now have a matching entry; fill the result and return */
entry->dwFileAttributes = fileinfo.dwFileAttributes;
@@ -1887,94 +1835,6 @@
return 0; /* End of directory */
}
-/***********************************************************************
- * DOSFS_FindNext
- *
- * Find the next matching file. Return the number of entries read to find
- * the matching one, or 0 if no more entries.
- * 'short_mask' is the 8.3 mask (in FCB format), 'long_mask' is the long
- * file name mask. Either or both can be NULL.
- *
- * NOTE: This is supposed to be only called by the int21 emulation
- * routines, and so assumes that the Win16Mutex is held to
- * protect the static directory cache.
- */
-int DOSFS_FindNext( const char *path, const char *short_mask,
- const char *long_mask, int drive, BYTE attr,
- int skip, WIN32_FIND_DATAA *entry )
-{
- static FIND_FIRST_INFO info;
- LPCWSTR short_name, long_name;
- int count;
- UNICODE_STRING short_maskW, long_maskW;
- WIN32_FIND_DATAW entryW;
-
- TRACE("(%s, %s, %s, %x, %x, %x, %p)\n", debugstr_a(path),
- debugstr_a(short_mask), debugstr_a(long_mask), drive, attr, skip,
- entry);
-
- RtlCreateUnicodeStringFromAsciiz(&short_maskW, short_mask);
- RtlCreateUnicodeStringFromAsciiz(&long_maskW, long_mask);
-
- /* Check the cached directory */
- if (!(info.u.dos_dir && info.path == path && !strcmpW(info.short_mask, short_maskW.Buffer)
- && !strcmpW(info.long_mask, long_maskW.Buffer) && info.drive == drive
- && info.attr == attr && info.cur_pos <= skip))
- {
- /* Not in the cache, open it anew */
- if (info.u.dos_dir) DOSFS_CloseDir( info.u.dos_dir );
-
- info.path = (LPSTR)path;
- RtlFreeHeap(GetProcessHeap(), 0, info.long_mask);
- RtlFreeHeap(GetProcessHeap(), 0, info.short_mask);
- info.long_mask = long_maskW.Buffer;
- info.short_mask = short_maskW.Buffer;
- info.attr = attr;
- info.drive = drive;
- info.cur_pos = 0;
- info.u.dos_dir = DOSFS_OpenDir( info.path );
- }
- else
- {
- RtlFreeUnicodeString(&short_maskW);
- RtlFreeUnicodeString(&long_maskW);
- }
-
- /* Skip to desired position */
- while (info.cur_pos < skip)
- if (info.u.dos_dir && DOSFS_ReadDir( info.u.dos_dir, &long_name, &short_name ))
- info.cur_pos++;
- else
- break;
-
- if (info.u.dos_dir && info.cur_pos == skip && DOSFS_FindNextEx( &info, &entryW ))
- {
- WideCharToMultiByte(CP_ACP, 0, entryW.cFileName, -1,
- entry->cFileName, sizeof(entry->cFileName), NULL, NULL);
- WideCharToMultiByte(CP_ACP, 0, entryW.cAlternateFileName, -1,
- entry->cAlternateFileName, sizeof(entry->cAlternateFileName), NULL, NULL);
- count = info.cur_pos - skip;
-
- entry->dwFileAttributes = entryW.dwFileAttributes;
- entry->nFileSizeHigh = entryW.nFileSizeHigh;
- entry->nFileSizeLow = entryW.nFileSizeLow;
- entry->ftCreationTime = entryW.ftCreationTime;
- entry->ftLastAccessTime = entryW.ftLastAccessTime;
- entry->ftLastWriteTime = entryW.ftLastWriteTime;
-
- }
- else
- count = 0;
-
- if (!count)
- {
- if (info.u.dos_dir) DOSFS_CloseDir( info.u.dos_dir );
- memset( &info, '\0', sizeof(info) );
- }
-
- return count;
-}
-
/*************************************************************************
* FindFirstFileExW (KERNEL32.@)
*/
@@ -2048,8 +1908,6 @@
info->long_mask = HeapAlloc( GetProcessHeap(), 0, long_mask_len * sizeof(WCHAR) );
MultiByteToWideChar(CP_UNIXCP, 0, p, -1, info->long_mask, long_mask_len);
- info->short_mask = NULL;
- info->attr = 0xff;
info->drive = full_name.drive;
info->cur_pos = 0;
@@ -2470,12 +2328,3 @@
return ret;
}
-
-/***********************************************************************
- * DefineDosDeviceA (KERNEL32.@)
- */
-BOOL WINAPI DefineDosDeviceA(DWORD flags,LPCSTR devname,LPCSTR targetpath) {
- FIXME("(0x%08lx,%s,%s),stub!\n",flags,devname,targetpath);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
-}
diff -u -N -r -x '*~' -x '.#*' -x CVS files35/drive.c files/drive.c
--- files35/drive.c 2003-11-09 19:31:34.000000000 +0100
+++ files/drive.c 2003-11-11 22:26:52.000000000 +0100
@@ -1283,21 +1283,54 @@
/***********************************************************************
- * 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] */
+ UNICODE_STRING d, t;
+ BOOL ret;
+ if (!RtlCreateUnicodeStringFromAsciiz(&d, devname))
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+ if (!RtlCreateUnicodeStringFromAsciiz(&t, targetpath))
+ {
+ RtlFreeUnicodeString(&d);
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+ ret = DefineDosDeviceW(flags, d.Buffer, t.Buffer);
+ RtlFreeUnicodeString(&d);
+ RtlFreeUnicodeString(&t);
+ return ret;
+}
+
+
+/***********************************************************************
+ * DefineDosDeviceA (KERNEL32.@)
+ */
+BOOL WINAPI DefineDosDeviceW(DWORD flags,LPCWSTR devname,LPCWSTR targetpath)
+{
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 ||
+ !(toupperW(devname[0]) >= 'A' && toupperW(devname[0]) <= 'Z') ||
+ devname[1] != ':' || devname[2] != 0 ||
+ !(toupperW(targetpath[0]) >= 'A' && toupperW(targetpath[0]) <= 'Z') ||
+ targetpath[1] != ':' || targetpath[2] != '\\' || targetpath[3] != 0)
+ {
+ FIXME("(0x%08lx,%s,%s),stub!\n", flags, debugstr_w(devname), debugstr_w(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 +1339,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 +1360,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 +2159,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;
}
diff -u -N -r -x '*~' -x '.#*' -x CVS include35/drive.h include/drive.h
--- include35/drive.h 2003-11-09 19:31:36.000000000 +0100
+++ include/drive.h 2003-11-13 21:18:10.000000000 +0100
@@ -51,7 +51,6 @@
extern int DRIVE_Chdir( int drive, LPCWSTR path );
extern int DRIVE_Disable( int drive );
extern int DRIVE_Enable( int drive );
-extern int DRIVE_SetLogicalMapping ( int existing_drive, int new_drive );
extern int DRIVE_OpenDevice( int drive, int flags );
extern WCHAR *DRIVE_BuildEnv(void);
diff -u -N -r -x '*~' -x '.#*' -x CVS include35/file.h include/file.h
--- include35/file.h 2003-11-09 19:31:36.000000000 +0100
+++ include/file.h 2003-11-11 22:18:51.000000000 +0100
@@ -97,9 +97,6 @@
INT long_len, LPWSTR short_buf, BOOL ignore_case );
extern BOOL DOSFS_GetFullName( LPCWSTR name, BOOL check_last,
DOS_FULL_NAME *full );
-extern int DOSFS_FindNext( const char *path, const char *short_mask,
- const char *long_mask, int drive, BYTE attr,
- int skip, WIN32_FIND_DATAA *entry );
/* win32/device.c */
extern HANDLE DEVICE_Open( LPCWSTR filename, DWORD access, LPSECURITY_ATTRIBUTES sa );
diff -u -N -r -x '*~' -x '.#*' -x CVS include35/msdos.h include/msdos.h
--- include35/msdos.h 2003-09-13 21:06:50.000000000 +0200
+++ include/msdos.h 2003-11-11 11:32:25.000000000 +0100
@@ -44,7 +44,7 @@
BYTE search_attr; /* 0c search attributes */
WORD count; /* 0d entry count within directory */
WORD cluster; /* 0f cluster of parent directory */
- char *unixPath; /* 11 unix path (was: reserved) */
+ void *fullPath; /* 11 full path (was: reserved) */
BYTE fileattr; /* 15 file attributes */
WORD filetime; /* 16 file time */
WORD filedate; /* 18 file date */
@@ -58,7 +58,7 @@
BYTE drive; /* 00 drive letter */
char filename[11]; /* 01 filename 8+3 format */
int count; /* 0c entry count (was: reserved) */
- char *unixPath; /* 10 unix path (was: reserved) */
+ void *fullPath; /* 10 full path (was: reserved) */
} FINDFILE_FCB;
/* DOS directory entry for FindFirstFCB/FindNextFCB */
diff -u -N -r -x '*~' -x '.#*' -x CVS include35/winbase.h include/winbase.h
--- include35/winbase.h 2003-11-12 21:47:43.000000000 +0100
+++ include/winbase.h 2003-11-12 20:55:57.000000000 +0100
@@ -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,10 +1189,16 @@
void WINAPI DebugBreak(void);
BOOL WINAPI DebugBreakProcess(HANDLE);
BOOL WINAPI DebugSetProcessKillOnExit(BOOL);
+BOOL WINAPI DefineDosDeviceA(DWORD,LPCSTR,LPCSTR);
+BOOL WINAPI DefineDosDeviceW(DWORD,LPCWSTR,LPCWSTR);
+#define DefineDosDevice WINELIB_NAME_AW(DefineDosDevice)
BOOL WINAPI DeleteAce(PACL,DWORD);
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);
@@ -1224,6 +1237,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*);
@@ -1323,6 +1350,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);
@@ -1473,6 +1509,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);
More information about the wine-patches
mailing list