Add prototype for GetCompressedFileSize. Move some int21 functions to

winedos. Improve file attribute functions.
This commit is contained in:
Jukka Heinonen 2003-03-30 03:04:37 +00:00 committed by Alexandre Julliard
parent ac89a159ac
commit 6f6eb82dfc
3 changed files with 397 additions and 168 deletions

View File

@ -43,6 +43,11 @@
*/
extern void WINAPI INT_Int21Handler( CONTEXT86 *context );
/*
* Forward declarations.
*/
static BOOL INT21_RenameFile( CONTEXT86 *context );
WINE_DEFAULT_DEBUG_CHANNEL(int21);
@ -357,6 +362,49 @@ static void INT21_BufferedInput( CONTEXT86 *context )
}
/***********************************************************************
* INT21_CreateDirectory
*
* Handler for:
* - function 0x39
* - subfunction 0x39 of function 0x71
* - subfunction 0xff of function 0x43 (CL == 0x39)
*/
static BOOL INT21_CreateDirectory( CONTEXT86 *context )
{
WCHAR dirW[MAX_PATH];
char *dirA = CTX_SEG_OFF_TO_LIN(context,
context->SegDs,
context->Edx);
TRACE( "CREATE DIRECTORY %s\n", dirA );
MultiByteToWideChar(CP_OEMCP, 0, dirA, -1, dirW, MAX_PATH);
if (CreateDirectoryW(dirW, NULL))
return TRUE;
/*
* FIXME: CreateDirectory's LastErrors will clash with the ones
* used by DOS. AH=39 only returns 3 (path not found) and
* 5 (access denied), while CreateDirectory return several
* ones. Remap some of them. -Marcus
*/
switch (GetLastError())
{
case ERROR_ALREADY_EXISTS:
case ERROR_FILENAME_EXCED_RANGE:
case ERROR_DISK_FULL:
SetLastError(ERROR_ACCESS_DENIED);
break;
default:
break;
}
return FALSE;
}
/***********************************************************************
* INT21_ExtendedCountryInformation
*
@ -478,6 +526,257 @@ static void INT21_ExtendedCountryInformation( CONTEXT86 *context )
}
/***********************************************************************
* INT21_FileAttributes
*
* Handler for:
* - function 0x43
* - subfunction 0x43 of function 0x71
*/
static BOOL INT21_FileAttributes( CONTEXT86 *context,
BYTE subfunction,
BOOL islong )
{
WCHAR fileW[MAX_PATH];
char *fileA = CTX_SEG_OFF_TO_LIN(context,
context->SegDs,
context->Edx);
HANDLE handle;
BOOL status;
FILETIME filetime;
DWORD result;
WORD date, time;
switch (subfunction)
{
case 0x00: /* GET FILE ATTRIBUTES */
TRACE( "GET FILE ATTRIBUTES for %s\n", fileA );
MultiByteToWideChar(CP_OEMCP, 0, fileA, -1, fileW, MAX_PATH);
result = GetFileAttributesW( fileW );
if (result == -1)
return FALSE;
else
{
SET_CX( context, (WORD)result );
if (!islong)
SET_AX( context, (WORD)result ); /* DR DOS */
}
break;
case 0x01: /* SET FILE ATTRIBUTES */
TRACE( "SET FILE ATTRIBUTES 0x%02x for %s\n",
CX_reg(context), fileA );
MultiByteToWideChar(CP_OEMCP, 0, fileA, -1, fileW, MAX_PATH);
if (!SetFileAttributesW( fileW, CX_reg(context) ))
return FALSE;
break;
case 0x02: /* GET COMPRESSED FILE SIZE */
TRACE( "GET COMPRESSED FILE SIZE for %s\n", fileA );
MultiByteToWideChar(CP_OEMCP, 0, fileA, -1, fileW, MAX_PATH);
result = GetCompressedFileSizeW( fileW, NULL );
if (result == INVALID_FILE_SIZE)
return FALSE;
else
{
SET_AX( context, LOWORD(result) );
SET_DX( context, HIWORD(result) );
}
break;
case 0x03: /* SET FILE LAST-WRITTEN DATE AND TIME */
if (!islong)
INT_BARF( context, 0x21 );
else
{
TRACE( "SET FILE LAST-WRITTEN DATE AND TIME, file %s\n", fileA );
MultiByteToWideChar(CP_OEMCP, 0, fileA, -1, fileW, MAX_PATH);
handle = CreateFileW( fileW, GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, 0 );
if (handle == INVALID_HANDLE_VALUE)
return FALSE;
DosDateTimeToFileTime( DI_reg(context),
CX_reg(context),
&filetime );
status = SetFileTime( handle, NULL, NULL, &filetime );
CloseHandle( handle );
return status;
}
break;
case 0x04: /* GET FILE LAST-WRITTEN DATE AND TIME */
if (!islong)
INT_BARF( context, 0x21 );
else
{
TRACE( "GET FILE LAST-WRITTEN DATE AND TIME, file %s\n", fileA );
MultiByteToWideChar(CP_OEMCP, 0, fileA, -1, fileW, MAX_PATH);
handle = CreateFileW( fileW, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, 0 );
if (handle == INVALID_HANDLE_VALUE)
return FALSE;
status = GetFileTime( handle, NULL, NULL, &filetime );
if (status)
{
FileTimeToDosDateTime( &filetime, &date, &time );
SET_DI( context, date );
SET_CX( context, time );
}
CloseHandle( handle );
return status;
}
break;
case 0x05: /* SET FILE LAST ACCESS DATE */
if (!islong)
INT_BARF( context, 0x21 );
else
{
TRACE( "SET FILE LAST ACCESS DATE, file %s\n", fileA );
MultiByteToWideChar(CP_OEMCP, 0, fileA, -1, fileW, MAX_PATH);
handle = CreateFileW( fileW, GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, 0 );
if (handle == INVALID_HANDLE_VALUE)
return FALSE;
DosDateTimeToFileTime( DI_reg(context),
0,
&filetime );
status = SetFileTime( handle, NULL, &filetime, NULL );
CloseHandle( handle );
return status;
}
break;
case 0x06: /* GET FILE LAST ACCESS DATE */
if (!islong)
INT_BARF( context, 0x21 );
else
{
TRACE( "GET FILE LAST ACCESS DATE, file %s\n", fileA );
MultiByteToWideChar(CP_OEMCP, 0, fileA, -1, fileW, MAX_PATH);
handle = CreateFileW( fileW, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, 0 );
if (handle == INVALID_HANDLE_VALUE)
return FALSE;
status = GetFileTime( handle, NULL, &filetime, NULL );
if (status)
{
FileTimeToDosDateTime( &filetime, &date, NULL );
SET_DI( context, date );
}
CloseHandle( handle );
return status;
}
break;
case 0x07: /* SET FILE CREATION DATE AND TIME */
if (!islong)
INT_BARF( context, 0x21 );
else
{
TRACE( "SET FILE CREATION DATE AND TIME, file %s\n", fileA );
handle = CreateFileW( fileW, GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, 0 );
if (handle == INVALID_HANDLE_VALUE)
return FALSE;
/*
* FIXME: SI has number of 10-millisecond units past time in CX.
*/
DosDateTimeToFileTime( DI_reg(context),
CX_reg(context),
&filetime );
status = SetFileTime( handle, &filetime, NULL, NULL );
CloseHandle( handle );
return status;
}
break;
case 0x08: /* GET FILE CREATION DATE AND TIME */
if (!islong)
INT_BARF( context, 0x21 );
else
{
TRACE( "GET FILE CREATION DATE AND TIME, handle %d\n",
BX_reg(context) );
handle = CreateFileW( fileW, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, 0 );
if (handle == INVALID_HANDLE_VALUE)
return FALSE;
status = GetFileTime( handle, &filetime, NULL, NULL );
if (status)
{
FileTimeToDosDateTime( &filetime, &date, &time );
SET_DI( context, date );
SET_CX( context, time );
/*
* FIXME: SI has number of 10-millisecond units past
* time in CX.
*/
SET_SI( context, 0 );
}
CloseHandle(handle);
return status;
}
break;
case 0xff: /* EXTENDED-LENGTH FILENAME OPERATIONS */
if (islong || context->Ebp != 0x5053)
INT_BARF( context, 0x21 );
else
{
switch(CL_reg(context))
{
case 0x39:
if (!INT21_CreateDirectory( context ))
return FALSE;
break;
case 0x56:
if (!INT21_RenameFile( context ))
return FALSE;
break;
default:
INT_BARF( context, 0x21 );
}
}
break;
default:
INT_BARF( context, 0x21 );
}
return TRUE;
}
/***********************************************************************
* INT21_FileDateTime
*
@ -751,10 +1050,14 @@ static void INT21_LongFilename( CONTEXT86 *context )
switch (AL_reg(context))
{
case 0x0d: /* RESET DRIVE */
case 0x39: /* LONG FILENAME - MAKE DIRECTORY */
INT_Int21Handler( context );
break;
case 0x39: /* LONG FILENAME - MAKE DIRECTORY */
if (!INT21_CreateDirectory( context ))
bSetDOSExtendedError = TRUE;
break;
case 0x3a: /* LONG FILENAME - REMOVE DIRECTORY */
{
WCHAR dirW[MAX_PATH];
@ -788,6 +1091,10 @@ static void INT21_LongFilename( CONTEXT86 *context )
break;
case 0x43: /* LONG FILENAME - EXTENDED GET/SET FILE ATTRIBUTES */
if (!INT21_FileAttributes( context, BL_reg(context), TRUE ))
bSetDOSExtendedError = TRUE;
break;
case 0x47: /* LONG FILENAME - GET CURRENT DIRECTORY */
case 0x4e: /* LONG FILENAME - FIND FIRST MATCHING FILE */
case 0x4f: /* LONG FILENAME - FIND NEXT MATCHING FILE */
@ -795,21 +1102,8 @@ static void INT21_LongFilename( CONTEXT86 *context )
break;
case 0x56: /* LONG FILENAME - RENAME FILE */
{
WCHAR fromW[MAX_PATH];
WCHAR toW[MAX_PATH];
char *fromA = CTX_SEG_OFF_TO_LIN(context,
context->SegDs,context->Edx);
char *toA = CTX_SEG_OFF_TO_LIN(context,
context->SegEs,context->Edi);
TRACE( "LONG FILENAME - RENAME FILE %s to %s\n", fromA, toA );
MultiByteToWideChar(CP_OEMCP, 0, fromA, -1, fromW, MAX_PATH);
MultiByteToWideChar(CP_OEMCP, 0, toA, -1, toW, MAX_PATH);
if (!MoveFileW( fromW, toW ))
bSetDOSExtendedError = TRUE;
}
if (!INT21_RenameFile(context))
bSetDOSExtendedError = TRUE;
break;
case 0x60: /* LONG FILENAME - CONVERT PATH */
@ -836,6 +1130,31 @@ static void INT21_LongFilename( CONTEXT86 *context )
}
/***********************************************************************
* INT21_RenameFile
*
* Handler for:
* - function 0x56
* - subfunction 0x56 of function 0x71
* - subfunction 0xff of function 0x43 (CL == 0x56)
*/
static BOOL INT21_RenameFile( CONTEXT86 *context )
{
WCHAR fromW[MAX_PATH];
WCHAR toW[MAX_PATH];
char *fromA = CTX_SEG_OFF_TO_LIN(context,
context->SegDs,context->Edx);
char *toA = CTX_SEG_OFF_TO_LIN(context,
context->SegEs,context->Edi);
TRACE( "RENAME FILE %s to %s\n", fromA, toA );
MultiByteToWideChar(CP_OEMCP, 0, fromA, -1, fromW, MAX_PATH);
MultiByteToWideChar(CP_OEMCP, 0, toA, -1, toW, MAX_PATH);
return MoveFileW( fromW, toW );
}
/***********************************************************************
* INT21_GetExtendedError
*/
@ -1349,7 +1668,8 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
break;
case 0x39: /* "MKDIR" - CREATE SUBDIRECTORY */
INT_Int21Handler( context );
if (!INT21_CreateDirectory( context ))
bSetDOSExtendedError = TRUE;
break;
case 0x3a: /* "RMDIR" - REMOVE DIRECTORY */
@ -1380,7 +1700,38 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
break;
case 0x3f: /* "READ" - READ FROM FILE OR DEVICE */
INT_Int21Handler( context );
TRACE( "READ from %d to %04lX:%04X for %d bytes\n",
BX_reg(context),
context->SegDs,
DX_reg(context),
CX_reg(context) );
{
DWORD result;
WORD count = CX_reg(context);
BYTE *buffer = CTX_SEG_OFF_TO_LIN( context,
context->SegDs,
context->Edx );
/* Some programs pass a count larger than the allocated buffer */
if (DOSVM_IsWin16())
{
WORD maxcount = GetSelectorLimit16( context->SegDs )
- DX_reg(context) + 1;
if (count > maxcount)
count = maxcount;
}
/*
* FIXME: Reading from console (BX=1) in DOS mode
* does not work as it is supposed to work.
*/
if (ReadFile( DosFileHandleToWin32Handle(BX_reg(context)),
buffer, count, &result, NULL ))
SET_AX( context, (WORD)result );
else
bSetDOSExtendedError = TRUE;
}
break;
case 0x40: /* "WRITE" - WRITE TO FILE OR DEVICE */
@ -1425,8 +1776,30 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
break;
case 0x42: /* "LSEEK" - SET CURRENT FILE POSITION */
TRACE( "LSEEK handle %d offset %ld from %s\n",
BX_reg(context),
MAKELONG( DX_reg(context), CX_reg(context) ),
(AL_reg(context) == 0) ?
"start of file" : ((AL_reg(context) == 1) ?
"current file position" : "end of file") );
{
HANDLE handle = DosFileHandleToWin32Handle(BX_reg(context));
LONG offset = MAKELONG( DX_reg(context), CX_reg(context) );
DWORD status = SetFilePointer( handle, offset,
NULL, AL_reg(context) );
if (status == INVALID_SET_FILE_POINTER)
bSetDOSExtendedError = TRUE;
else
{
SET_AX( context, LOWORD(status) );
SET_DX( context, HIWORD(status) );
}
}
break;
case 0x43: /* FILE ATTRIBUTES */
INT_Int21Handler( context );
if (!INT21_FileAttributes( context, AL_reg(context), FALSE ))
bSetDOSExtendedError = TRUE;
break;
case 0x44: /* IOCTL */
@ -1617,21 +1990,8 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
break;
case 0x56: /* "RENAME" - RENAME FILE */
{
WCHAR fromW[MAX_PATH];
WCHAR toW[MAX_PATH];
char *fromA = CTX_SEG_OFF_TO_LIN(context,
context->SegDs,context->Edx);
char *toA = CTX_SEG_OFF_TO_LIN(context,
context->SegEs,context->Edi);
TRACE( "RENAME %s to %s\n", fromA, toA );
MultiByteToWideChar(CP_OEMCP, 0, fromA, -1, fromW, MAX_PATH);
MultiByteToWideChar(CP_OEMCP, 0, toA, -1, toW, MAX_PATH);
if (!MoveFileW( fromW, toW ))
bSetDOSExtendedError = TRUE;
}
if (!INT21_RenameFile( context ))
bSetDOSExtendedError = TRUE;
break;
case 0x57: /* FILE DATE AND TIME */

View File

@ -1300,6 +1300,9 @@ BOOL WINAPI GetCommTimeouts(HANDLE,LPCOMMTIMEOUTS);
LPSTR WINAPI GetCommandLineA(void);
LPWSTR WINAPI GetCommandLineW(void);
#define GetCommandLine WINELIB_NAME_AW(GetCommandLine)
DWORD WINAPI GetCompressedFileSizeA(LPCSTR,LPDWORD);
DWORD WINAPI GetCompressedFileSizeW(LPCWSTR,LPDWORD);
#define GetCompressedFileSize WINELIB_NAME_AW(GetCompressedFileSize)
BOOL WINAPI GetComputerNameA(LPSTR,LPDWORD);
BOOL WINAPI GetComputerNameW(LPWSTR,LPDWORD);
#define GetComputerName WINELIB_NAME_AW(GetComputerName)

View File

@ -1020,28 +1020,6 @@ void WINAPI INT_Int21Handler( CONTEXT86 *context )
if (!INT21_GetFreeDiskSpace(context)) SET_AX( context, 0xffff );
break;
case 0x39: /* "MKDIR" - CREATE SUBDIRECTORY */
TRACE("MKDIR %s\n",
(LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx));
bSetDOSExtendedError = (!CreateDirectory16( CTX_SEG_OFF_TO_LIN(context, context->SegDs,
context->Edx ), NULL));
/* FIXME: CreateDirectory's LastErrors will clash with the ones
* used by dos. AH=39 only returns 3 (path not found) and 5 (access
* denied), while CreateDirectory return several ones. remap some of
* them. -Marcus
*/
if (bSetDOSExtendedError) {
switch (GetLastError()) {
case ERROR_ALREADY_EXISTS:
case ERROR_FILENAME_EXCED_RANGE:
case ERROR_DISK_FULL:
SetLastError(ERROR_ACCESS_DENIED);
break;
default: break;
}
}
break;
case 0x3b: /* "CHDIR" - SET CURRENT DIRECTORY */
TRACE("CHDIR %s\n",
(LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx));
@ -1060,69 +1038,6 @@ void WINAPI INT_Int21Handler( CONTEXT86 *context )
OpenExistingFile(context);
break;
case 0x3f: /* "READ" - READ FROM FILE OR DEVICE */
TRACE("READ from %d to %04lX:%04X for %d byte\n",BX_reg(context),
context->SegDs,DX_reg(context),CX_reg(context) );
{
LONG result;
if (ISV86(context))
result = _hread16( BX_reg(context),
CTX_SEG_OFF_TO_LIN(context, context->SegDs,
context->Edx ),
CX_reg(context) );
else
result = WIN16_hread( BX_reg(context),
MAKESEGPTR( context->SegDs, context->Edx ),
CX_reg(context) );
if (result == -1) bSetDOSExtendedError = TRUE;
else SET_AX( context, (WORD)result );
}
break;
case 0x42: /* "LSEEK" - SET CURRENT FILE POSITION */
TRACE("LSEEK handle %d offset %ld from %s\n",
BX_reg(context), MAKELONG(DX_reg(context),CX_reg(context)),
(AL_reg(context)==0)?"start of file":(AL_reg(context)==1)?
"current file position":"end of file");
{
LONG status = _llseek16( BX_reg(context),
MAKELONG(DX_reg(context),CX_reg(context)),
AL_reg(context) );
if (status == -1) bSetDOSExtendedError = TRUE;
else
{
SET_AX( context, LOWORD(status) );
SET_DX( context, HIWORD(status) );
}
}
break;
case 0x43: /* FILE ATTRIBUTES */
switch (AL_reg(context))
{
case 0x00:
TRACE("GET FILE ATTRIBUTES for %s\n",
(LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx));
SET_AX( context, GetFileAttributesA( CTX_SEG_OFF_TO_LIN(context, context->SegDs,
context->Edx)));
if (AX_reg(context) == 0xffff) bSetDOSExtendedError = TRUE;
else SET_CX( context, AX_reg(context) );
break;
case 0x01:
TRACE("SET FILE ATTRIBUTES 0x%02x for %s\n", CX_reg(context),
(LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx));
bSetDOSExtendedError =
(!SetFileAttributesA( CTX_SEG_OFF_TO_LIN(context, context->SegDs,
context->Edx),
CX_reg(context) ));
break;
case 0x02:
FIXME("GET COMPRESSED FILE SIZE for %s stub\n",
(LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx));
}
break;
case 0x44: /* IOCTL */
switch (AL_reg(context))
{
@ -1334,55 +1249,6 @@ void WINAPI INT_Int21Handler( CONTEXT86 *context )
case 0x71: /* MS-DOS 7 (Windows95) - LONG FILENAME FUNCTIONS */
switch(AL_reg(context))
{
case 0x39: /* Create directory */
TRACE("LONG FILENAME - MAKE DIRECTORY %s\n",
(LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs,context->Edx));
bSetDOSExtendedError = (!CreateDirectoryA(
CTX_SEG_OFF_TO_LIN(context, context->SegDs,
context->Edx ), NULL));
/* FIXME: CreateDirectory's LastErrors will clash with the ones
* used by dos. AH=39 only returns 3 (path not found) and 5 (access
* denied), while CreateDirectory return several ones. remap some of
* them. -Marcus
*/
if (bSetDOSExtendedError) {
switch (GetLastError()) {
case ERROR_ALREADY_EXISTS:
case ERROR_FILENAME_EXCED_RANGE:
case ERROR_DISK_FULL:
SetLastError(ERROR_ACCESS_DENIED);
break;
default: break;
}
}
break;
case 0x43: /* Get/Set file attributes */
TRACE("LONG FILENAME -EXTENDED GET/SET FILE ATTRIBUTES %s\n",
(LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs,context->Edx));
switch (BL_reg(context))
{
case 0x00: /* Get file attributes */
TRACE("\tretrieve attributes\n");
SET_CX( context, GetFileAttributesA( CTX_SEG_OFF_TO_LIN(context, context->SegDs,
context->Edx)));
if (CX_reg(context) == 0xffff) bSetDOSExtendedError = TRUE;
break;
case 0x01:
TRACE("\tset attributes 0x%04x\n",CX_reg(context));
bSetDOSExtendedError = (!SetFileAttributesA(
CTX_SEG_OFF_TO_LIN(context, context->SegDs,
context->Edx),
CX_reg(context) ) );
break;
default:
FIXME("Unimplemented long file name function:\n");
INT_BARF( context, 0x21 );
SET_CFLAG(context);
SET_AL( context, 0 );
break;
}
break;
case 0x47: /* Get current directory */
TRACE(" LONG FILENAME - GET CURRENT DIRECTORY for drive %s\n",
INT21_DriveName(DL_reg(context)));