final int21 move (2/11)
György 'Nog' Jeney
nog at sdf.lonestar.org
Wed Nov 27 14:12:57 CST 2002
> On November 27, 2002 12:37 pm, György 'Nog' Jeney wrote:
>> ChangeLog:
>> * dlls/winedos/int21.c
>> * msdos/int21.c
>> * include/msdos.h
>> * files/dos_fs.h
>> * include/file.h
>> Move Find{First|Next}{FCB|} fucntions to winedos.
>
> Dude, where's the patch? :)
Right here :)
nog.
-------------- next part --------------
--- msdos/int21.c.1 2002-11-27 15:36:00.000000000 +0200
+++ msdos/int21.c 2002-11-27 15:36:23.000000000 +0200
@@ -159,16 +159,6 @@
return TRUE;
}
-static BYTE *GetCurrentDTA( CONTEXT86 *context )
-{
- TDB *pTask = TASK_GetCurrent();
-
- /* FIXME: This assumes DTA was set correctly! */
- return (BYTE *)CTX_SEG_OFF_TO_LIN( context, SELECTOROF(pTask->dta),
- (DWORD)OFFSETOF(pTask->dta) );
-}
-
-
void CreateBPB(int drive, BYTE *data, BOOL16 limited)
/* limited == TRUE is used with INT 0x21/0x440d */
{
@@ -424,50 +414,6 @@
return FALSE;
}
-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;
- len = 0;
- while (*s)
- {
- if ((*s != ' ') && (*s != '\r') && (*s != '\n'))
- {
- s++;
- len++;
- }
- else
- break;
- }
-
- 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;
- DOSFS_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 );
-}
-
static void INT21_GetSystemDate( CONTEXT86 *context )
{
SYSTEMTIME systime;
@@ -639,92 +585,6 @@
return DRIVE_Chdir( drive, dirnameW );
}
-
-static int INT21_FindFirst( CONTEXT86 *context )
-{
- char *p;
- const char *path;
- DOS_FULL_NAME full_name;
- FINDFILE_DTA *dta = (FINDFILE_DTA *)GetCurrentDTA(context);
- WCHAR pathW[MAX_PATH];
- WCHAR maskW[12];
-
- path = (const char *)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
- MultiByteToWideChar(CP_OEMCP, 0, path, -1, pathW, MAX_PATH);
-
- dta->unixPath = NULL;
- if (!DOSFS_GetFullName( pathW, FALSE, &full_name ))
- {
- SET_AX( context, GetLastError() );
- SET_CFLAG(context);
- return 0;
- }
- dta->unixPath = HeapAlloc( GetProcessHeap(), 0, strlen(full_name.long_name)+1 );
- strcpy( dta->unixPath, full_name.long_name );
- p = strrchr( dta->unixPath, '/' );
- *p = '\0';
-
- MultiByteToWideChar(CP_OEMCP, 0, p + 1, -1, pathW, MAX_PATH);
-
- /* Note: terminating NULL in dta->mask overwrites dta->search_attr
- * (doesn't matter as it is set below anyway)
- */
- if (!DOSFS_ToDosFCBFormat( pathW, maskW ))
- {
- HeapFree( GetProcessHeap(), 0, dta->unixPath );
- dta->unixPath = 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);
- dta->drive = (path[0] && (path[1] == ':')) ? toupper(path[0]) - 'A'
- : DRIVE_GetCurrentDrive();
- dta->count = 0;
- dta->search_attr = CL_reg(context);
- return 1;
-}
-
-
-static int INT21_FindNext( CONTEXT86 *context )
-{
- FINDFILE_DTA *dta = (FINDFILE_DTA *)GetCurrentDTA(context);
- WIN32_FIND_DATAA entry;
- int count;
-
- if (!dta->unixPath) return 0;
- if (!(count = DOSFS_FindNext( dta->unixPath, dta->mask, NULL, dta->drive,
- dta->search_attr, dta->count, &entry )))
- {
- HeapFree( GetProcessHeap(), 0, dta->unixPath );
- dta->unixPath = NULL;
- return 0;
- }
- if ((int)dta->count + count > 0xffff)
- {
- WARN("Too many directory entries in %s\n", dta->unixPath );
- HeapFree( GetProcessHeap(), 0, dta->unixPath );
- dta->unixPath = NULL;
- return 0;
- }
- dta->count += count;
- dta->fileattr = entry.dwFileAttributes;
- dta->filesize = entry.nFileSizeLow;
- FileTimeToDosDateTime( &entry.ftLastWriteTime,
- &dta->filedate, &dta->filetime );
- strcpy( dta->filename, entry.cAlternateFileName );
- 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->unixPath );
- dta->unixPath = NULL;
- }
- return 1;
-}
-
-
static BOOL INT21_CreateTempFile( CONTEXT86 *context )
{
static int counter = 0;
@@ -820,99 +680,6 @@
/* microsoft's programmers should be shot for using CP/M style int21
calls in Windows for Workgroup's winfile.exe */
-static int INT21_FindFirstFCB( CONTEXT86 *context )
-{
- BYTE *fcb = (BYTE *)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
- FINDFILE_FCB *pFCB;
- LPCSTR root, cwd;
- int drive;
-
- if (*fcb == 0xff) pFCB = (FINDFILE_FCB *)(fcb + 7);
- else pFCB = (FINDFILE_FCB *)fcb;
- drive = DOS_GET_DRIVE( pFCB->drive );
- if (!DRIVE_IsValid( drive )) return 0;
- root = DRIVE_GetRoot( drive );
- cwd = DRIVE_GetUnixCwd( drive );
- pFCB->unixPath = HeapAlloc( GetProcessHeap(), 0,
- strlen(root)+strlen(cwd)+2 );
- if (!pFCB->unixPath) return 0;
- strcpy( pFCB->unixPath, root );
- strcat( pFCB->unixPath, "/" );
- strcat( pFCB->unixPath, cwd );
- pFCB->count = 0;
- return 1;
-}
-
-
-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 *)GetCurrentDTA(context);
- WIN32_FIND_DATAA entry;
- BYTE attr;
- int count;
-
- if (*fcb == 0xff) /* extended FCB ? */
- {
- attr = fcb[6];
- pFCB = (FINDFILE_FCB *)(fcb + 7);
- }
- else
- {
- attr = 0;
- pFCB = (FINDFILE_FCB *)fcb;
- }
-
- if (!pFCB->unixPath) return 0;
- if (!(count = DOSFS_FindNext( pFCB->unixPath, pFCB->filename, NULL,
- DOS_GET_DRIVE( pFCB->drive ), attr,
- pFCB->count, &entry )))
- {
- HeapFree( GetProcessHeap(), 0, pFCB->unixPath );
- pFCB->unixPath = NULL;
- return 0;
- }
- pFCB->count += count;
-
- 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 = DOS_GET_DRIVE( 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 */
-
- memset( pResult->filename, ' ', sizeof(pResult->filename) );
- if (!strcmp( entry.cAlternateFileName, "." )) pResult->filename[0] = '.';
- else if (!strcmp( entry.cAlternateFileName, ".." ))
- pResult->filename[0] = pResult->filename[1] = '.';
- else
- {
- char *p = strrchr( entry.cAlternateFileName, '.' );
- if (p && p[1] && (p != entry.cAlternateFileName))
- {
- memcpy( pResult->filename, entry.cAlternateFileName,
- min( (p - entry.cAlternateFileName), 8 ) );
- memcpy( pResult->filename + 8, p + 1, min( strlen(p), 3 ) );
- }
- else
- memcpy( pResult->filename, entry.cAlternateFileName,
- min( strlen(entry.cAlternateFileName), 8 ) );
- }
- return 1;
-}
-
-
static void DeleteFileFCB( CONTEXT86 *context )
{
FIXME("(%p): stub\n", context);
@@ -1095,20 +862,6 @@
SET_AL( context, MAX_DOS_DRIVES );
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 */
- SET_AL( context, INT21_FindNextFCB(context) ? 0x00 : 0xff );
- break;
-
case 0x13: /* DELETE FILE USING FCB */
DeleteFileFCB(context);
break;
@@ -1117,10 +870,6 @@
RenameFileFCB(context);
break;
- case 0x19: /* GET CURRENT DEFAULT DRIVE */
- SET_AL( context, DRIVE_GetCurrentDrive() );
- break;
-
case 0x1a: /* SET DISK TRANSFER AREA ADDRESS */
{
TDB *pTask = TASK_GetCurrent();
@@ -1142,10 +891,6 @@
GetDrivePB(context, DRIVE_GetCurrentDrive());
break;
- case 0x29: /* PARSE FILENAME INTO FCB */
- INT21_ParseFileNameIntoFCB(context);
- break;
-
case 0x2a: /* GET SYSTEM DATE */
INT21_GetSystemDate(context);
break;
@@ -1567,12 +1312,6 @@
bSetDOSExtendedError = (FILE_Dup2( BX_reg(context), CX_reg(context) ) == HFILE_ERROR16);
break;
- case 0x47: /* "CWD" - GET CURRENT DIRECTORY */
- TRACE("CWD - GET CURRENT DIRECTORY for drive %s\n",
- INT21_DriveName( DL_reg(context)));
- bSetDOSExtendedError = !INT21_GetCurrentDirectory(context);
- break;
-
case 0x48: /* ALLOCATE MEMORY */
TRACE("ALLOCATE MEMORY for %d paragraphs\n", BX_reg(context));
{
@@ -1636,23 +1375,6 @@
}
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 */
- 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 0x54: /* Get Verify Flag */
TRACE("Get Verify Flag - Not Supported\n");
SET_AL( context, 0x00 ); /* pretend we can tell. 00h = off 01h = on */
--- dlls/winedos/int21.c.1 2002-11-27 15:36:09.000000000 +0200
+++ dlls/winedos/int21.c 2002-11-27 15:37:33.000000000 +0200
@@ -6,6 +6,7 @@
* Copyright 1997 Andreas Mohr
* Copyright 1998 Uwe Bonnes
* Copyright 1998, 1999 Ove Kaaven
+ * Copyright 2002 Gyorgy 'Nog' Jeney
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -34,11 +35,578 @@
#include "miscemu.h"
#include "msdos.h"
#include "file.h"
+#include "task.h"
#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(int21);
+/***********************************************************************
+ * GetDosDrive [internal]
+ *
+ * returns a 0 based identifier of the dos drive passed to it. If it is 0
+ * then it returns the current drive.
+ *
+ * PARAMS:
+ * drive [I]: The drive to return its 0 based id.
+ *
+ * RETURNS:
+ * Zero based drive ID.
+ */
+static int GetDosDrive(int drive)
+{
+ if(drive)
+ return drive - 1;
+ else {
+ char root[MAX_PATH];
+ GetCurrentDirectoryA(MAX_PATH, root);
+ return toupper(*root) - 'A';
+ }
+}
+
+/***********************************************************************
+ * IsDriveValid [internal]
+ *
+ * Check to see if the 0 based drive ID passed to it is valid
+ *
+ * PARAMS:
+ * drive [I]: Drive to check for validity.
+ *
+ * RETURNS:
+ * 0: Drive is invalid.
+ * 1: Drive is valid.
+ */
+static int IsDriveValid(int drive)
+{
+ char driveA[] = "A:\\";
+ UINT res;
+
+ *driveA += drive;
+ res = GetDriveTypeA(driveA);
+
+ if((res == DRIVE_NO_ROOT_DIR) || (res == DRIVE_UNKNOWN))
+ return 0;
+
+ return 1;
+}
+
+/* Many calls translate a drive argument like this:
+ * drive number (00h = default, 01h = A:, etc)
+ */
+static char drivestring[] = "default";
+
+/***********************************************************************
+ * INT21_DriveName [internal]
+ *
+ * Returns a string which displays the drive in drive. If drive is 0 then
+ * is means 'default' dirve.
+ *
+ * PARAMS:
+ * drive [I]: Drive to return a string for.
+ *
+ * RETURNS:
+ * Null trminated character string which displays the drive.
+ */
+char *INT21_DriveName(int drive)
+{
+ if(drive > 0) {
+ drivestring[0] = (unsigned char)drive + '@';
+ drivestring[1] = ':';
+ drivestring[2] = 0;
+ }
+ return drivestring;
+}
+
+/***********************************************************************
+ * INT21_GetCurrentDirectory [internal]
+ *
+ * Returns the current directory for a given drive.
+ *
+ * PARAMS:
+ * ptr [O]: Pointer to a buffer to hold the directory.
+ * driveg [I]: Drive who's current directory is to be retrieved.
+ *
+ * RETURNS:
+ * TRUE: Sucessful.
+ * FALSE: Failure.
+ *
+ * NOTES:
+ * Mabe we should check if the directory is a valid dos directory name.
+ */
+static BOOL INT21_GetCurrentDirectory(char *ptr, int driveg)
+{
+ int drive = GetDosDrive(driveg);
+ int defdrive = GetDosDrive(0);
+ char curdir[66];
+
+ if(!IsDriveValid(drive)) {
+ SetLastError(ERROR_INVALID_DRIVE);
+ return FALSE;
+ }
+
+ if(defdrive != drive) {
+ char driveA[] = "a:";
+ *driveA += drive;
+ SetCurrentDirectoryA(driveA);
+ }
+
+ if(GetCurrentDirectoryA(66, curdir))
+ strcpy(ptr, curdir + 3);
+
+ if(defdrive != drive) {
+ char driveA[] = "a:";
+ *driveA += defdrive;
+ SetCurrentDirectoryA(driveA);
+ }
+
+ ptr[63] = 0; /* ensure 0 termination */
+
+ TRACE("Current directory in drive %d is %s\n", drive, ptr);
+
+ return TRUE;
+}
+
+/***********************************************************************
+ * GetCurrentDTA [internal]
+ *
+ * Returns a pointer to the current DTA.
+ *
+ * PARAMS:
+ * context [I]: Pointer to structure holding registers.
+ *
+ * RETURNS:
+ * Pointer to the current DTA.
+ */
+static BYTE *GetCurrentDTA(CONTEXT86 *context)
+{
+ TDB *pTask = GlobalLock16(GetCurrentTask());
+
+ return (BYTE *)CTX_SEG_OFF_TO_LIN(context, SELECTOROF(pTask->dta),
+ (DWORD)OFFSETOF(pTask->dta));
+}
+
+/***********************************************************************
+ * INT21_ParseToFCB [internal]
+ *
+ * Parses a filename to a valid FCB file name according to pcontrol.
+ *
+ * PARAMS:
+ * file [I]: Valid Dos filename.
+ * fcb [O]: Pointer to buffer to hold FCB
+ * pcontrol [I]: What to do if there are filename bits missing.
+ * drive [O]: The drive that is mentioned in the filename.
+ * unparsed [O]: Location of the first unparsed char relative to the filename. *
+ * RETURNS:
+ * TRUE: There are wild cards in the filename.
+ * FALSE: There are no wild cards in the filename.
+ *
+ * NOTES:
+ * This code could be cleaned up some more.
+ */
+static BOOL INT21_ParseToFCB(const char *file, char *fcb, BYTE pcontrol,
+ int *drive, int *unparsed)
+{
+ int len = 0;
+ const char *lastback = NULL;
+ BOOL ext = FALSE;
+ BOOL wild = FALSE;
+ char nfcb[12];
+
+ TRACE("filename: %s control: %02x\n", file, pcontrol);
+
+ while(file[len] && (file[len] != ' ') && (file[len] != '\r') &&
+ (file[len] != '\n')) {
+ if(file[len] == '\\')
+ lastback = &file[len + 1];
+ len++;
+ }
+
+ /* Check to see if a drive was specified */
+ if(lastback && (*file != '\\')) {
+ /* There was a drive specified */
+ if(drive) *drive = 'A' - toupper(*file);
+ } else {
+ /* Drive was not specified, see if we set the drive to zero or not */
+ if(!(pcontrol & 0x2))
+ if(drive) *drive = 0;
+ }
+
+ if(!lastback) lastback = file;
+
+ if(*lastback == '.') {
+ /* There is no filename specified */
+ if(!(pcontrol & 0x4)) /* Fill filename space with spaces */
+ memset(fcb, ' ', 8);
+ len = 8;
+ lastback++;
+ ext = TRUE;
+ } else
+ len = 0;
+
+ for(; *lastback && (*lastback != ' ') && (*lastback != '\r') &&
+ (*lastback != '\n'); lastback++, len++) {
+ if(len == 12)
+ break;
+
+ switch(*lastback) {
+ case '.':
+ /* Pad the filname with spaces */
+ if(ext) {
+ TRACE("Illeagel filename, it has more than one extension\n");
+ len = 11;
+ } else {
+ memset(&fcb[len], ' ', 8 - len);
+ len = 7; /* the for construct will increment it */
+ ext = TRUE;
+ }
+ break;
+ case '*':
+ wild = TRUE;
+ /* Pad the rest of the filename with ?s */
+ if(ext) {
+ memset(&fcb[len], '?', 11 - len);
+ len = 11;
+ } else
+ memset(&fcb[len], '?', 8 - len);
+ break;
+ case '?':
+ wild = TRUE;
+ /* fall through */
+ default:
+ fcb[len] = toupper(*lastback);
+ }
+ }
+
+ if(!ext && (len == 8)) {
+ /* check to see what we should do if there is no extension */
+ if(!(pcontrol & 0x8))
+ memset(fcb + 8, ' ', 3);
+ } else if(len < 11)
+ /* pad the fcb extension with spaces */
+ memset(fcb + len, ' ', 11 - len);
+
+ memcpy(nfcb, fcb, 11);
+
+ nfcb[11] = 0;
+
+ TRACE("FCB: %s\n", nfcb);
+
+ if(unparsed) *unparsed = lastback - file;
+
+ return wild;
+}
+
+/***********************************************************************
+ * INT21_FCBToFile [internal]
+ *
+ * Parses an FCB filename back to a normal filename.
+ *
+ * PARAMS:
+ * dest [O]: Pointer to buffer to hold filename.
+ * fcb [I]: FCB filename to parse.
+ *
+ * RETURNS:
+ * Nothing.
+ */
+static void INT21_FCBToFile(char *dest, char *fcb)
+{
+ int n;
+
+ TRACE("FCB: %s\n", fcb);
+
+ for(n = 0; n < 11; n++, fcb++, dest++) {
+ if(n == 8) {
+ *dest = '.';
+ dest++;
+ }
+
+ if(*fcb != ' ')
+ *dest = *fcb;
+ }
+
+ *dest = 0;
+
+ TRACE("Filname: %s\n", dest);
+}
+
+/***********************************************************************
+ * INT21_NextFile [internal]
+ *
+ * Helper function for Find{First|Next}{File|FCB}. Check to see if the
+ * attributes match and copies the relevent information from entry to
+ * to buffers.
+ *
+ * PARAMS:
+ * entry [I]: Pointer to a valid WIN32_FIND_DATAA as returned by
+ * Find{First|Next}FileA.
+ * file [O]: Pointer to a buffer to hold the filename.
+ * attr [O]: Pointer to a buffer to hold the attributes of the file.
+ * data [O]: Pointer to a buffer to hold the last acess date of the file.
+ * time [O]: Pointer to a buffer to hold the last acess time of the file.
+ * size [O]: Pointer to a buffer to hold the size of the file.
+ * findattr [I]: The search attributes.
+ *
+ * RETURNS:
+ * 0: Attributes don't match.
+ * 1: Attributes match.
+ */
+static int INT21_NextFile(WIN32_FIND_DATAA *entry, char *file, BYTE *attr,
+ WORD *date, WORD *time, DWORD *size, BYTE findattr)
+{
+ TRACE("Attribute of found file: 0x%lx, find attributes: 0x%x\n",
+ entry->dwFileAttributes & 0x3f, findattr);
+
+ if((findattr & entry->dwFileAttributes & 0x3f)) {
+ *attr = entry->dwFileAttributes;
+ FileTimeToDosDateTime(&entry->ftLastWriteTime, date, time);
+ *size = entry->nFileSizeLow;
+ strcpy(file, entry->cAlternateFileName);
+ TRACE("Search attributes match, returning %s\n", file);
+ return 1;
+ }
+
+ *file = 0;
+ return 0;
+}
+
+/***********************************************************************
+ * INT21_FindFirst [internal]
+ *
+ * Implementation of the find fisrt function (0x4e).
+ *
+ * PARAMS:
+ * context [I]: Pointer to structure holding registers.
+ *
+ * RETURNS:
+ * 0: Failure.
+ * 1: Success.
+ */
+static int INT21_FindFirst(CONTEXT86 *context)
+{
+ const char *path;
+ FINDFILE_DTA *dta = (FINDFILE_DTA *)GetCurrentDTA(context);
+ int count = 0;
+ WIN32_FIND_DATAA entry;
+
+ path = (const char *)CTX_SEG_OFF_TO_LIN(context, context->SegDs,
+ context->Edx);
+
+ /* Fill in the DTA */
+ INT21_ParseToFCB(path, dta->mask, 0, NULL, NULL);
+ dta->search_attr = CX_reg(context);
+ if(!dta->search_attr) {
+ /* If attributes are 0 then we are to find files that have no attributes * set, but since dos doesn't treat it this way, we won't. Dos treets
+ * it as find archive */
+ dta->search_attr = 0x20;
+ }
+ dta->count = 0;
+ dta->cluster = 0; /* What are we meant to do here ?? */
+ dta->drive = GetDosDrive(0);
+ *dta->filename = 0;
+
+ if((dta->handle = FindFirstFileA(path, &entry)) == INVALID_HANDLE_VALUE)
+ return 0;
+
+findagain:
+
+ if(!INT21_NextFile(&entry, dta->filename, &dta->fileattr, &dta->filedate,
+ &dta->filetime, &dta->filesize, dta->search_attr)) {
+ /* Continue searching */
+ if(FindNextFileA(dta->handle, &entry)) {
+ count++;
+ goto findagain;
+ } else {
+ FindClose(dta->handle);
+ TRACE("No matching files found\n");
+ return 0;
+ }
+ }
+
+ 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 */
+ FindClose(dta->handle);
+ }
+
+ return 1;
+}
+
+/***********************************************************************
+ * INT21_FindNext [internal]
+ *
+ * Implementation of FindNext file function (0x4f).
+ *
+ * PARAMS:
+ * context [I]: Pointer to structure holding registers.
+ *
+ * RETURNS:
+ * 0: Failure.
+ * 1: Sucess.
+ */
+static int INT21_FindNext(CONTEXT86 *context)
+{
+ FINDFILE_DTA *dta = (FINDFILE_DTA *)GetCurrentDTA(context);
+ WIN32_FIND_DATAA entry;
+ int count = dta->count;
+
+ for(;; ++count) {
+ if(FindNextFileA(dta->handle, &entry)) {
+ if(!INT21_NextFile(&entry, dta->filename, &dta->fileattr,
+ &dta->filedate, &dta->filetime, &dta->filesize,
+ dta->search_attr)) {
+ FindClose(dta->handle);
+ return 0;
+ } else
+ dta->count = count;
+ } else {
+ TRACE("No more matching files found\n");
+ *dta->filename = 0;
+ FindClose(dta->handle);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/***********************************************************************
+ * INT21_FindFirstFCB [internal]
+ *
+ * Implementation of Find First using FCB.
+ *
+ * PARAMS:
+ * context [I]: Pointer to structure holding registers.
+ *
+ * RETURNS:
+ * 0: No file found.
+ * 1: Files found.
+ */
+static int INT21_FindFirstFCB(CONTEXT86 *context)
+{
+ FINDFILE_FCB *fcb;
+ BYTE *efcb = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
+ char path[MAX_PATH];
+ HANDLE findh;
+ WIN32_FIND_DATAA entry;
+ DOS_DIRENTRY_LAYOUT *dta = (DOS_DIRENTRY_LAYOUT *)GetCurrentDTA(context);
+ int attr = 0;
+
+ if(*efcb == 0xff) {
+ fcb = (FINDFILE_FCB *)(efcb + 7);
+ attr = efcb[6];
+ } else fcb = (FINDFILE_FCB *)efcb;
+
+ if(!INT21_GetCurrentDirectory(path, fcb->drive))
+ return 0;
+
+ memmove(path + 3, path, 63);
+ memcpy(path, "A:\\", 3);
+ *path += GetDosDrive(fcb->drive);
+
+ INT21_FCBToFile(&path[strlen(path) + 1], fcb->filename);
+
+ if((findh = FindFirstFileA(path, &entry)) == INVALID_HANDLE_VALUE)
+ return 0;
+
+findagain:
+
+ if(*efcb == 0xff) {
+ *(BYTE *)dta = 0xff;
+ (BYTE *)dta += 7; /* Place the extended FCB header first */
+ }
+
+ /* DOS_DIRENTRY_LAYOUT after current drive number */
+ *(BYTE *)dta = GetDosDrive(fcb->drive);
+ ((BYTE *)dta)++;
+
+ if(!INT21_NextFile(&entry, path, &dta->fileattr, &dta->filedate,
+ &dta->filetime, &dta->filesize, attr)) {
+ /* Continue searching */
+ if(FindNextFileA(fcb->findh, &entry)) {
+ goto findagain;
+ } else {
+ TRACE("No more file found\n");
+ FindClose(findh);
+ return 0;
+ }
+ }
+
+ INT21_ParseToFCB(path, dta->filename, 0, NULL, NULL);
+
+ if(*efcb == 0xff) {
+ ((BYTE *)dta)--;
+ *(BYTE *)dta = entry.dwFileAttributes;
+ }
+
+ if (!memchr(fcb->filename, '?', 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 */
+ FindClose(findh);
+ }
+
+ return 1;
+}
+
+/***********************************************************************
+ * INT21_FindNextFCB [internal]
+ *
+ * Implementation of FindNextFCB.
+ *
+ * PARAMS:
+ * context [I]: Pointer to structure holding registers.
+ *
+ * RETURNS:
+ * 0: No files found.
+ * 1: Files found.
+ */
+static int INT21_FindNextFCB(CONTEXT86 *context)
+{
+ FINDFILE_FCB *fcb;
+ BYTE *efcb = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
+ WIN32_FIND_DATAA entry;
+ DOS_DIRENTRY_LAYOUT *dta = (DOS_DIRENTRY_LAYOUT *)GetCurrentDTA(context);
+ int attr = 0;
+ char file[MAX_PATH];
+
+ if(*efcb == 0xff) {
+ fcb = (FINDFILE_FCB *)(efcb + 7);
+ attr = efcb[6];
+ } else fcb = (FINDFILE_FCB *)efcb;
+
+ if(*efcb == 0xff) {
+ *(BYTE *)dta = 0xff;
+ (BYTE *)dta += 7; /* Place the extended FCB header first */
+ }
+
+ /* DOS_DIRENTRY_LAYOUT after current drive number */
+ *(BYTE *)dta = GetDosDrive(fcb->drive);
+ ((BYTE *)dta)++;
+
+ for(;;) {
+ if(FindNextFileA(fcb->findh, &entry)) {
+ if(INT21_NextFile(&entry, file, &dta->fileattr, &dta->filedate,
+ &dta->filetime, &dta->filesize, attr))
+ break;
+ /* Continue searching */
+ } else {
+ TRACE("No more file found\n");
+ FindClose(fcb->findh);
+ return 0;
+ }
+ }
+
+ INT21_ParseToFCB(file, dta->filename, 0, NULL, NULL);
+
+ if(*efcb == 0xff) {
+ ((BYTE *)dta)--;
+ *(BYTE *)dta = entry.dwFileAttributes;
+ }
+
+ return 1;
+}
+
void WINAPI DOSVM_Int21Handler_Ioctl( CONTEXT86 *context )
{
static const WCHAR emmxxxx0W[] = {'E','M','M','X','X','X','X','0',0};
@@ -293,6 +861,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));
+ SET_AL(context, INT21_FindFirstFCB(context) ? 0x00 : 0xff);
+ break;
+
+ case 0x12: /* FIND NEXT MATCHING FILE USING FCB */
+ SET_AL(context, INT21_FindNextFCB(context) ? 0x00 : 0xff);
+ break;
+
+ case 0x19: /* GET CURRENT DEFAULT DRIVE */
+ SET_AL(context, GetDosDrive(0));
+ break;
+
case 0x25: /* SET INTERRUPT VECTOR */
if(DOSVM_IsWin16()) DOSVM_SetPMHandler16(AL_reg(context),
(FARPROC16)MAKESEGPTR(context->SegDs,
@@ -302,6 +884,21 @@
DX_reg(context)));
break;
+ case 0x29: /* PARSE FILENAME INTO FCB */
+ {
+ FINDFILE_FCB *fcb = CTX_SEG_OFF_TO_LIN(context, context->SegEs,
+ context->Edi);
+ int unp;
+ if(INT21_ParseToFCB(CTX_SEG_OFF_TO_LIN(context, context->SegDs,
+ context->Esi), fcb->filename, AL_reg(context), (int *)&fcb->drive, &unp))
+ SET_AL(context, 1);
+ else
+ SET_AL(context, 0);
+
+ SET_SI(context, context->Esi + unp);
+ }
+ break;
+
case 0x35: /* GET INTERRUPT VECTOR */
{
FARPROC16 addr;
@@ -333,6 +930,16 @@
DOSVM_Int21Handler_Ioctl( context );
break;
+ case 0x47: /* "CWD" - GET CURRENT DIRECTORY */
+ TRACE("CWD - GET CURRENT DIRECTORY for %s drive\n",
+ INT21_DriveName(DL_reg(context)));
+ if(!(bSetDOSExtendedError = !INT21_GetCurrentDirectory(
+ (char *)CTX_SEG_OFF_TO_LIN(context,
+ context->SegDs, context->Esi),
+ DL_reg(context))))
+ SET_AX(context, 0x0100); /* success return code */
+ break;
+
case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */
TRACE("EXEC %s\n", (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs,
context->Edx));
@@ -362,6 +969,24 @@
DOSVM_retval = 0;
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)) {
+ SetLastError(ERROR_NO_MORE_FILES);
+ bSetDOSExtendedError = TRUE;
+ }
+ break;
+
+ case 0x4f: /* "FINDNEXT" - FIND NEXT MATCHING FILE */
+ TRACE("FINDNEXT\n");
+ if(!INT21_FindNext(context))
+ {
+ SetLastError(ERROR_NO_MORE_FILES);
+ bSetDOSExtendedError = TRUE;
+ }
+ else SET_AX(context, 0); /* OK */
+ break;
+
case 0x50: /* SET CURRENT PROCESS ID (SET PSP ADDRESS) */
TRACE("SET CURRENT PROCESS ID (SET PSP ADDRESS)\n");
DOSVM_psp = BX_reg(context);
--- ../readwritewine/include/msdos.h 2002-06-01 01:06:48.000000000 +0200
+++ include/msdos.h 2002-11-27 15:36:23.000000000 +0200
@@ -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 *handle; /* 11 windows find handle (was: reserved) */
BYTE fileattr; /* 15 file attributes */
WORD filetime; /* 16 file time */
WORD filedate; /* 18 file date */
@@ -57,8 +57,8 @@
{
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) */
+ int reserved; /* 0c reserved */
+ void *findh; /* 10 windows find handle (was: reserved) */
} FINDFILE_FCB;
/* DOS directory entry for FindFirstFCB/FindNextFCB */
--- ../readwritewine/files/dos_fs.c 2002-11-21 09:37:00.000000000 +0200
+++ files/dos_fs.c 2002-11-27 15:36:23.000000000 +0200
@@ -1808,99 +1808,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. Thus, we should own the Win16Mutex anyway.
- * Nevertheless, we explicitly enter it to ensure the static
- * directory cache is protected.
- */
-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);
-
- _EnterWin16Lock();
-
- 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( DRIVE_GetCodepage(drive), 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) );
- }
-
- _LeaveWin16Lock();
-
- return count;
-}
-
/*************************************************************************
* FindFirstFileExW (KERNEL32.@)
*/
--- ../readwritewine/include/file.h 2002-11-24 03:18:29.000000000 +0200
+++ include/file.h 2002-11-27 15:36:23.000000000 +0200
@@ -104,9 +104,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 );
/* profile.c */
extern void PROFILE_UsageWineIni(void);
More information about the wine-devel
mailing list