final int21 move (7/11)
György 'Nog' Jeney
nog at sdf.lonestar.org
Wed Nov 27 12:26:47 CST 2002
ChangeLog:
* dlls/winedos/int21.c
* msdos/int21.c
* dlls/ntdll/Makefile.in
* dlls/winedos/Makefile.in
* include/miscemu.h
* dlls/winedos/dosexe.h
* dlls/winedos/dosconf.c
Move fucntion 33h to winedos.
nog.
-------------- next part --------------
--- dlls/winedos/int21.c.5 2002-11-27 15:53:56.000000000 +0200
+++ dlls/winedos/int21.c 2002-11-27 15:57:05.000000000 +0200
@@ -1756,6 +1756,310 @@
(LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edi)); bSetDOSExtendedError = !INT21_ExtendedOpenCreateFile(context);
break;
+ case 0x70: /* MS-DOS 7 (Windows95) - ??? (country-specific?)*/
+ TRACE("windows95 function AX %04x\n",
+ AX_reg(context));
+ WARN(" returning unimplemented\n");
+ SET_CFLAG(context);
+ SET_AL( context, 0 );
+ break;
+
+ case 0x71: /* MS-DOS 7 (Windows95) - LONG FILENAME FUNCTIONS */
+ if ((GetVersion()&0xC0000004)!=0xC0000004) {
+ /* not supported on anything but Win95 */
+ TRACE("LONG FILENAME functions supported only by win95\n");
+ SET_CFLAG(context);
+ SET_AL( context, 0 );
+ } else
+ 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 0x3a: /* Remove directory */
+ TRACE("LONG FILENAME - REMOVE DIRECTORY %s\n",
+ (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs,
+ context->Edx));
+ bSetDOSExtendedError = (!RemoveDirectoryA(
+ CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx )));
+ 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)));
+ 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 0x4e: /* Find first file */
+ TRACE(" LONG FILENAME - FIND FIRST MATCHING FILE for %s\n",
+ (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs,
+ context->Edx));
+ {
+ HANDLE findh;
+ findh = FindFirstFileA(
+ CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx), (WIN32_FIND_DATAA *)CTX_SEG_OFF_TO_LIN(context,
+ context->SegEs,
+ context->Edi));
+ if(findh == INVALID_HANDLE_VALUE)
+ bSetDOSExtendedError = TRUE;
+ else {
+ HGLOBAL16 handle = GlobalAlloc16(GMEM_MOVEABLE,
+ sizeof(HANDLE));
+ if(!handle) {
+ FindClose(findh);
+ bSetDOSExtendedError = TRUE;
+ break;
+ }
+
+ *(HANDLE *)GlobalLock16(handle) = findh;
+ GlobalUnlock16(handle);
+
+ SET_AX(context, handle);
+ }
+ }
+ break;
+ case 0x4f: /* Find next file */
+ TRACE("LONG FILENAME - FIND NEXT MATCHING FILE for handle %d\n",
+ BX_reg(context));
+ if(!FindNextFileA(*(HANDLE *)GlobalLock16(BX_reg(context)),
+ (WIN32_FIND_DATAA *)CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edi)))
+ bSetDOSExtendedError = TRUE;
+ GlobalUnlock16(BX_reg(context));
+ break;
+ case 0xa0:
+ {
+ LPCSTR driveroot = (LPCSTR)CTX_SEG_OFF_TO_LIN(context,
+ context->SegDs,
+ context->Edx);
+ LPSTR buffer =(LPSTR)CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edi);
+ DWORD filename_len, flags;
+
+ TRACE("LONG FILENAME - GET VOLUME INFORMATION for drive having " "root dir '%s'.\n", driveroot);
+ SET_AX(context, 0);
+ if(!GetVolumeInformationA(driveroot, NULL, 0, NULL,
+ &filename_len, &flags, buffer, 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 ? */
+ }
+ break;
+ case 0xa1: /* Find close */
+ TRACE("LONG FILENAME - FINDCLOSE for handle %d\n",
+ BX_reg(context));
+ bSetDOSExtendedError = (!FindClose(
+ *(HANDLE *)GlobalLock16(BX_reg(context)))); GlobalUnlock16(BX_reg(context));
+ GlobalFree16(BX_reg(context));
+ break;
+ case 0x60:
+ switch(CL_reg(context)) {
+ case 0x01: /* Get short filename or path */
+ if(!GetShortPathNameA(CTX_SEG_OFF_TO_LIN(context,
+ context->SegDs,
+ context->Esi),
+ CTX_SEG_OFF_TO_LIN(context,
+ context->SegEs,
+ context->Edi), 67))
+ bSetDOSExtendedError = TRUE;
+ else SET_AX( context, 0 );
+ break;
+ case 0x02: /* Get canonical long filename or path */
+ if(!GetFullPathNameA(CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Esi), 128,
+ CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edi), NULL))
+ bSetDOSExtendedError = TRUE;
+ else SET_AX( context, 0 );
+ break;
+ default:
+ FIXME("Unimplemented long file name function:\n");
+ INT_BARF(context, 0x21);
+ SET_CFLAG(context);
+ SET_AL(context, 0);
+ break;
+ }
+ break;
+ case 0x6c: /* Create or open file */
+ TRACE("LONG FILENAME - CREATE OR OPEN FILE %s\n",
+ (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs,
+ context->Esi));
+ /* translate Dos 7 action to Dos 6 action */
+ bSetDOSExtendedError = INT21_ExtendedOpenCreateFile(context);
+ break;
+
+ case 0x3b: /* Change directory */
+ TRACE("LONG FILENAME - CHANGE DIRECTORY %s\n",
+ (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs,
+ context->Edx));
+ if(!SetCurrentDirectoryA(CTX_SEG_OFF_TO_LIN(context,
+ context->SegDs,
+ context->Edx))) {
+ SET_CFLAG(context);
+ SET_AL(context, GetLastError());
+ }
+ break;
+ case 0x41: /* Delete file */
+ TRACE("LONG FILENAME - DELETE FILE %s\n",
+ (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs,
+ context->Edx));
+ if(!DeleteFileA(CTX_SEG_OFF_TO_LIN(context, context->SegDs,
+ context->Edx))) {
+ SET_CFLAG(context);
+ SET_AL(context, GetLastError());
+ }
+ break;
+ case 0x56: /* Move (rename) file */
+ {
+ LPCSTR fn1 = (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
+ LPCSTR fn2 = (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edi);
+ TRACE("LONG FILENAME - RENAME FILE %s to %s\n", fn1, fn2);
+ if(!MoveFileA(fn1, fn2)) {
+ SET_CFLAG(context);
+ SET_AL(context, GetLastError());
+ }
+ }
+ break;
+ default:
+ FIXME("Unimplemented long file name function:\n");
+ INT_BARF(context, 0x21);
+ SET_CFLAG(context);
+ SET_AL(context, 0);
+ break;
+ }
+ break;
+
+ case 0x72: /* MS-DOS 7 (Windows95) - ??? */
+ TRACE("windows95 function AX %04x\n", AX_reg(context));
+ WARN(" returning unimplemented\n");
+ SET_CFLAG(context);
+ SET_AL(context, 0);
+ break;
+
+ case 0x73: /* MULTIPLEXED: Win95 OSR2/Win98 FAT32 calls */
+ TRACE("windows95 function AX %04x\n", AX_reg(context));
+
+ switch (AL_reg(context)) {
+ case 0x02: /* Get Extended Drive Parameter Block for specific drive */
+ /* ES:DI points to word with length of data (should be 0x3d) */
+ {
+ WORD *buffer;
+ struct EDPB *edpb;
+ DWORD cluster_sectors, sector_bytes, free_clusters;
+ DWORD total_clusters;
+ char root[] = "A:\\";
+
+ buffer = (WORD *)CTX_SEG_OFF_TO_LIN(context, context->SegEs,
+ context->Edi);
+
+ TRACE("Get Extended DPB: linear buffer address is %p\n",
+ buffer);
+
+ /* validate passed-in buffer lengths */
+ if((*buffer != 0x3d) || (context->Ecx != 0x3f)) {
+ WARN("Get Extended DPB: buffer lengths incorrect\n");
+ WARN("CX = %lx, buffer[0] = %x\n", context->Ecx,
+ *buffer);
+ SET_CFLAG(context);
+ SET_AL(context, 0x18);
+ /* bad buffer length */
+ }
+
+ /* buffer checks out */
+ buffer++; /* skip over length word now */
+ if(FillInDrivePB( DX_reg(context) ) ) {
+ edpb = (struct EDPB *)buffer;
+
+ /* copy down the old-style DPB portion first */
+ memcpy(&edpb->dpb, &heap->dpb, sizeof(struct DPB));
+
+ /* now fill in the extended entries */
+ edpb->edpb_flags = 0;
+ edpb->next_edpb = 0;
+ edpb->free_cluster = edpb->free_cluster2 = 0;
+
+ /* determine free disk space */
+ *root += GetDosDrive(DX_reg(context));
+ GetDiskFreeSpaceA(root, &cluster_sectors, §or_bytes,
+ &free_clusters, &total_clusters);
+
+ edpb->clusters_free = (free_clusters&0xffff);
+
+ edpb->clusters_free_hi = free_clusters >> 16;
+ edpb->mirroring_flags = 0;
+ edpb->info_sector = 0xffff;
+ edpb->spare_boot_sector = 0xffff;
+ edpb->first_cluster = 0;
+ edpb->max_cluster = total_clusters;
+ edpb->fat_clusters = 32; /* made-up value */
+ edpb->root_cluster = 0;
+
+ RESET_CFLAG(context); /* clear carry */
+ SET_AX( context, 0 );
+ } else {
+ SET_AX( context, 0x00ff );
+ SET_CFLAG(context);
+ }
+ }
+ break;
+
+ case 0x03: /* Get Extended free space on drive */
+ case 0x04: /* Set DPB for formatting */
+ case 0x05: /* extended absolute disk read/write */
+ FIXME("Unimplemented FAT32 int32 function %04x\n",
+ AX_reg(context));
+ SET_CFLAG(context);
+ SET_AL(context, 0);
+ break;
+ }
+ break;
+
default:
DOS3Call( context );
}
--- msdos/int21.c.5 2002-11-27 15:53:45.000000000 +0200
+++ msdos/int21.c 2002-11-27 15:57:05.000000000 +0200
@@ -72,68 +72,7 @@
#define DOS_GET_DRIVE(reg) ((reg) ? (reg) - 1 : DRIVE_GetCurrentDrive())
-/* Define the drive parameter block, as used by int21/1F
- * and int21/32. This table can be accessed through the
- * global 'dpb' pointer, which points into the local dos
- * heap.
- */
-struct DPB
-{
- BYTE drive_num; /* 0=A, etc. */
- BYTE unit_num; /* Drive's unit number (?) */
- WORD sector_size; /* Sector size in bytes */
- BYTE high_sector; /* Highest sector in a cluster */
- BYTE shift; /* Shift count (?) */
- WORD reserved; /* Number of reserved sectors at start */
- BYTE num_FAT; /* Number of FATs */
- WORD dir_entries; /* Number of root dir entries */
- WORD first_data; /* First data sector */
- WORD high_cluster; /* Highest cluster number */
- WORD sectors_in_FAT; /* Number of sectors per FAT */
- WORD start_dir; /* Starting sector of first dir */
- DWORD driver_head; /* Address of device driver header (?) */
- BYTE media_ID; /* Media ID */
- BYTE access_flag; /* Prev. accessed flag (0=yes,0xFF=no) */
- DWORD next; /* Pointer to next DPB in list */
- WORD free_search; /* Free cluster search start */
- WORD free_clusters; /* Number of free clusters (0xFFFF=unknown) */
-};
-
-struct EDPB /* FAT32 extended Drive Parameter Block */
-{ /* from Ralf Brown's Interrupt List */
- struct DPB dpb; /* first 24 bytes = original DPB */
-
- BYTE edpb_flags; /* undocumented/unknown flags */
- DWORD next_edpb; /* pointer to next EDPB */
- WORD free_cluster; /* cluster to start search for free space on write, typically
- the last cluster allocated */
- WORD clusters_free; /* number of free clusters on drive or FFFF = unknown */
- WORD clusters_free_hi; /* hiword of clusters_free */
- WORD mirroring_flags; /* mirroring flags: bit 7 set = do not mirror active FAT */
- /* bits 0-3 = 0-based number of the active FAT */
- WORD info_sector; /* sector number of file system info sector, or FFFF for none */
- WORD spare_boot_sector; /* sector number of backup boot sector, or FFFF for none */
- DWORD first_cluster; /* sector number of the first cluster */
- DWORD max_cluster; /* sector number of the last cluster */
- DWORD fat_clusters; /* number of clusters occupied by FAT */
- DWORD root_cluster; /* cluster number of start of root directory */
- DWORD free_cluster2; /* same as free_cluster: cluster at which to start
- search for free space when writing */
-
-};
-
WORD CodePage = 437;
-DWORD dpbsegptr;
-
-struct DosHeap {
- BYTE InDosFlag;
- BYTE mediaID;
- BYTE biosdate[8];
- struct DPB dpb;
- BYTE DummyDBCSLeadTable[6];
-};
-static struct DosHeap *heap;
-static WORD DosHeapHandle;
extern char TempDirectory[];
@@ -144,21 +83,6 @@
done = 1;
}
-static BOOL INT21_CreateHeap(void)
-{
- if (!(DosHeapHandle = GlobalAlloc16(GMEM_FIXED,sizeof(struct DosHeap))))
- {
- WARN("Out of memory\n");
- return FALSE;
- }
- heap = (struct DosHeap *) GlobalLock16(DosHeapHandle);
- dpbsegptr = MAKESEGPTR(DosHeapHandle,(int)&heap->dpb-(int)heap);
- heap->InDosFlag = 0;
- strcpy(heap->biosdate, "01/01/80");
- memset(heap->DummyDBCSLeadTable, 0, 6);
- return TRUE;
-}
-
void CreateBPB(int drive, BYTE *data, BOOL16 limited)
/* limited == TRUE is used with INT 0x21/0x440d */
{
@@ -199,45 +123,6 @@
}
}
-static int FillInDrivePB( int drive )
-{
- if(!DRIVE_IsValid(drive))
- {
- SetLastError( ERROR_INVALID_DRIVE );
- return 0;
- }
- else if (heap || INT21_CreateHeap())
- {
- /* FIXME: I have no idea what a lot of this information should
- * say or whether it even really matters since we're not allowing
- * direct block access. However, some programs seem to depend on
- * getting at least _something_ back from here. The 'next' pointer
- * does worry me, though. Should we have a complete table of
- * separate DPBs per drive? Probably, but I'm lazy. :-) -CH
- */
- heap->dpb.drive_num = heap->dpb.unit_num = drive; /*The same?*/
- heap->dpb.sector_size = 512;
- heap->dpb.high_sector = 1;
- heap->dpb.shift = drive < 2 ? 0 : 6; /*6 for HD, 0 for floppy*/
- heap->dpb.reserved = 0;
- heap->dpb.num_FAT = 1;
- heap->dpb.dir_entries = 2;
- heap->dpb.first_data = 2;
- heap->dpb.high_cluster = 64000;
- heap->dpb.sectors_in_FAT = 1;
- heap->dpb.start_dir = 1;
- heap->dpb.driver_head = 0;
- heap->dpb.media_ID = (drive > 1) ? 0xF8 : 0xF0;
- heap->dpb.access_flag = 0;
- heap->dpb.next = 0;
- heap->dpb.free_search = 0;
- heap->dpb.free_clusters = 0xFFFF; /* unknown */
- return 1;
- }
-
- return 0;
-}
-
static void ioctlGetDeviceInfo( CONTEXT86 *context )
{
int curr_drive;
@@ -407,132 +292,6 @@
}
return drivestring;
}
-static BOOL INT21_CreateFile( CONTEXT86 *context )
-{
- SET_AX( context, _lcreat16( CTX_SEG_OFF_TO_LIN(context, context->SegDs,
- context->Edx ), CX_reg(context) ) );
- return (AX_reg(context) == (WORD)HFILE_ERROR16);
-}
-
-static void OpenExistingFile( CONTEXT86 *context )
-{
- SET_AX( context, _lopen16( CTX_SEG_OFF_TO_LIN(context, context->SegDs,context->Edx),
- AL_reg(context) ));
- if (AX_reg(context) == (WORD)HFILE_ERROR16)
- {
- SET_AX( context, GetLastError() );
- SET_CFLAG(context);
- }
-}
-
-static BOOL INT21_ExtendedOpenCreateFile(CONTEXT86 *context )
-{
- BOOL bExtendedError = FALSE;
- BYTE action = DL_reg(context);
-
- /* Shuffle arguments to call OpenExistingFile */
- SET_AL( context, BL_reg(context) );
- SET_DX( context, SI_reg(context) );
- /* BX,CX and DX should be preserved */
- OpenExistingFile(context);
-
- if ((context->EFlags & 0x0001) == 0) /* File exists */
- {
- UINT16 uReturnCX = 0;
-
- /* Now decide what do do */
-
- if ((action & 0x07) == 0)
- {
- _lclose16( AX_reg(context) );
- SET_AX( context, 0x0050 ); /*File exists*/
- SET_CFLAG(context);
- WARN("extended open/create: failed because file exists \n");
- }
- else if ((action & 0x07) == 2)
- {
- /* Truncate it, but first check if opened for write */
- if ((BL_reg(context) & 0x0007)== 0)
- {
- _lclose16( AX_reg(context) );
- WARN("extended open/create: failed, trunc on ro file\n");
- SET_AX( context, 0x000C ); /*Access code invalid*/
- SET_CFLAG(context);
- }
- else
- {
- TRACE("extended open/create: Closing before truncate\n");
- if (_lclose16( AX_reg(context) ))
- {
- WARN("extended open/create: close before trunc failed\n");
- SET_AX( context, 0x0019 ); /*Seek Error*/
- SET_CX( context, 0 );
- SET_CFLAG(context);
- }
- /* Shuffle arguments to call CreateFile */
-
- TRACE("extended open/create: Truncating\n");
- SET_AL( context, BL_reg(context) );
- /* CX is still the same */
- SET_DX( context, SI_reg(context) );
- bExtendedError = INT21_CreateFile(context);
-
- if (context->EFlags & 0x0001) /*no file open, flags set */
- {
- WARN("extended open/create: trunc failed\n");
- return bExtendedError;
- }
- uReturnCX = 0x3;
- }
- }
- else uReturnCX = 0x1;
-
- SET_CX( context, uReturnCX );
- }
- else /* file does not exist */
- {
- RESET_CFLAG(context); /* was set by OpenExistingFile(context) */
- if ((action & 0xF0)== 0)
- {
- SET_CX( context, 0 );
- SET_CFLAG(context);
- WARN("extended open/create: failed, file dosen't exist\n");
- }
- else
- {
- /* Shuffle arguments to call CreateFile */
- TRACE("extended open/create: Creating\n");
- SET_AL( context, BL_reg(context) );
- /* CX should still be the same */
- SET_DX( context, SI_reg(context) );
- bExtendedError = INT21_CreateFile(context);
- if (context->EFlags & 0x0001) /*no file open, flags set */
- {
- WARN("extended open/create: create failed\n");
- return bExtendedError;
- }
- SET_CX( context, 2 );
- }
- }
-
- return bExtendedError;
-}
-
-static BOOL INT21_GetCurrentDirectory( CONTEXT86 *context )
-{
- int drive = DOS_GET_DRIVE( DL_reg(context) );
- char *ptr = (char *)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Esi );
-
- if (!DRIVE_IsValid(drive))
- {
- SetLastError( ERROR_INVALID_DRIVE );
- return FALSE;
- }
- WideCharToMultiByte(CP_OEMCP, 0, DRIVE_GetDosCwd(drive), -1, ptr, 64, NULL, NULL);
- ptr[63] = 0; /* ensure 0 termination */
- SET_AX( context, 0x0100 ); /* success return code */
- return TRUE;
-}
static int INT21_GetDiskSerialNumber( CONTEXT86 *context )
{
@@ -1198,293 +957,6 @@
}
break;
- case 0x71: /* MS-DOS 7 (Windows95) - LONG FILENAME FUNCTIONS */
- if ((GetVersion()&0xC0000004)!=0xC0000004) {
- /* not supported on anything but Win95 */
- TRACE("LONG FILENAME functions supported only by win95\n");
- SET_CFLAG(context);
- SET_AL( context, 0 );
- } else
- 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 0x3a: /* Remove directory */
- TRACE("LONG FILENAME - REMOVE DIRECTORY %s\n",
- (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs,context->Edx));
- bSetDOSExtendedError = (!RemoveDirectoryA(
- CTX_SEG_OFF_TO_LIN(context, context->SegDs,
- context->Edx )));
- 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)));
- bSetDOSExtendedError = !INT21_GetCurrentDirectory(context);
- break;
-
- case 0x4e: /* Find first file */
- TRACE(" LONG FILENAME - FIND FIRST MATCHING FILE for %s\n",
- (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs,context->Edx));
- /* FIXME: use attributes in CX */
- if ((SET_AX( context, FindFirstFile16(
- CTX_SEG_OFF_TO_LIN(context, context->SegDs,context->Edx),
- (WIN32_FIND_DATAA *)CTX_SEG_OFF_TO_LIN(context, context->SegEs,
- context->Edi))))
- == INVALID_HANDLE_VALUE16)
- bSetDOSExtendedError = TRUE;
- break;
- case 0x4f: /* Find next file */
- TRACE("LONG FILENAME - FIND NEXT MATCHING FILE for handle %d\n",
- BX_reg(context));
- if (!FindNextFile16( BX_reg(context),
- (WIN32_FIND_DATAA *)CTX_SEG_OFF_TO_LIN(context, context->SegEs,
- context->Edi)))
- bSetDOSExtendedError = TRUE;
- break;
- case 0xa0:
- {
- LPCSTR driveroot = (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs,context->Edx);
- LPSTR buffer = (LPSTR)CTX_SEG_OFF_TO_LIN(context, context->SegEs,context->Edi);
- DWORD filename_len, flags;
-
- TRACE("LONG FILENAME - GET VOLUME INFORMATION for drive having root dir '%s'.\n", driveroot);
- SET_AX( context, 0 );
- if (!GetVolumeInformationA( driveroot, NULL, 0, NULL, &filename_len,
- &flags, buffer, 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 ? */
- }
- break;
- case 0xa1: /* Find close */
- TRACE("LONG FILENAME - FINDCLOSE for handle %d\n",
- BX_reg(context));
- bSetDOSExtendedError = (!FindClose16( BX_reg(context) ));
- break;
- case 0x60:
- switch(CL_reg(context))
- {
- case 0x01: /* Get short filename or path */
- if (!GetShortPathNameA
- ( CTX_SEG_OFF_TO_LIN(context, context->SegDs,
- context->Esi),
- CTX_SEG_OFF_TO_LIN(context, context->SegEs,
- context->Edi), 67))
- bSetDOSExtendedError = TRUE;
- else SET_AX( context, 0 );
- break;
- case 0x02: /* Get canonical long filename or path */
- if (!GetFullPathNameA
- ( CTX_SEG_OFF_TO_LIN(context, context->SegDs,
- context->Esi), 128,
- CTX_SEG_OFF_TO_LIN(context, context->SegEs,
- context->Edi),NULL))
- bSetDOSExtendedError = TRUE;
- else SET_AX( context, 0 );
- break;
- default:
- FIXME("Unimplemented long file name function:\n");
- INT_BARF( context, 0x21 );
- SET_CFLAG(context);
- SET_AL( context, 0 );
- break;
- }
- break;
- case 0x6c: /* Create or open file */
- TRACE("LONG FILENAME - CREATE OR OPEN FILE %s\n",
- (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Esi));
- /* translate Dos 7 action to Dos 6 action */
- bSetDOSExtendedError = INT21_ExtendedOpenCreateFile(context);
- break;
-
- case 0x3b: /* Change directory */
- TRACE("LONG FILENAME - CHANGE DIRECTORY %s\n",
- (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx));
- if (!SetCurrentDirectoryA(CTX_SEG_OFF_TO_LIN(context,
- context->SegDs,
- context->Edx
- ))
- ) {
- SET_CFLAG(context);
- SET_AL( context, GetLastError() );
- }
- break;
- case 0x41: /* Delete file */
- TRACE("LONG FILENAME - DELETE FILE %s\n",
- (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx));
- if (!DeleteFileA(CTX_SEG_OFF_TO_LIN(context,
- context->SegDs,
- context->Edx)
- )) {
- SET_CFLAG(context);
- SET_AL( context, GetLastError() );
- }
- break;
- case 0x56: /* Move (rename) file */
- {
- LPCSTR fn1 = (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
- LPCSTR fn2 = (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edi);
- TRACE("LONG FILENAME - RENAME FILE %s to %s\n", fn1, fn2);
- if (!MoveFileA(fn1, fn2))
- {
- SET_CFLAG(context);
- SET_AL( context, GetLastError() );
- }
- }
- break;
- default:
- FIXME("Unimplemented long file name function:\n");
- INT_BARF( context, 0x21 );
- SET_CFLAG(context);
- SET_AL( context, 0 );
- break;
- }
- break;
-
- case 0x70: /* MS-DOS 7 (Windows95) - ??? (country-specific?)*/
- case 0x72: /* MS-DOS 7 (Windows95) - ??? */
- TRACE("windows95 function AX %04x\n",
- AX_reg(context));
- WARN(" returning unimplemented\n");
- SET_CFLAG(context);
- SET_AL( context, 0 );
- break;
-
- case 0x73: /* MULTIPLEXED: Win95 OSR2/Win98 FAT32 calls */
- TRACE("windows95 function AX %04x\n",
- AX_reg(context));
-
- switch (AL_reg(context))
- {
- case 0x02: /* Get Extended Drive Parameter Block for specific drive */
- /* ES:DI points to word with length of data (should be 0x3d) */
- {
- WORD *buffer;
- struct EDPB *edpb;
- DWORD cluster_sectors, sector_bytes, free_clusters, total_clusters;
- char root[] = "A:\\";
-
- buffer = (WORD *)CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edi);
-
- TRACE("Get Extended DPB: linear buffer address is %p\n", buffer);
-
- /* validate passed-in buffer lengths */
- if ((*buffer != 0x3d) || (context->Ecx != 0x3f))
- {
- WARN("Get Extended DPB: buffer lengths incorrect\n");
- WARN("CX = %lx, buffer[0] = %x\n", context->Ecx, *buffer);
- SET_CFLAG(context);
- SET_AL( context, 0x18 ); /* bad buffer length */
- }
-
- /* buffer checks out */
- buffer++; /* skip over length word now */
- if (FillInDrivePB( DX_reg(context) ) )
- {
- edpb = (struct EDPB *)buffer;
-
- /* copy down the old-style DPB portion first */
- memcpy(&edpb->dpb, &heap->dpb, sizeof(struct DPB));
-
- /* now fill in the extended entries */
- edpb->edpb_flags = 0;
- edpb->next_edpb = 0;
- edpb->free_cluster = edpb->free_cluster2 = 0;
-
- /* determine free disk space */
- *root += DOS_GET_DRIVE( DX_reg(context) );
- GetDiskFreeSpaceA( root, &cluster_sectors, §or_bytes,
- &free_clusters, &total_clusters );
-
- edpb->clusters_free = (free_clusters&0xffff);
-
- edpb->clusters_free_hi = free_clusters >> 16;
- edpb->mirroring_flags = 0;
- edpb->info_sector = 0xffff;
- edpb->spare_boot_sector = 0xffff;
- edpb->first_cluster = 0;
- edpb->max_cluster = total_clusters;
- edpb->fat_clusters = 32; /* made-up value */
- edpb->root_cluster = 0;
-
- RESET_CFLAG(context); /* clear carry */
- SET_AX( context, 0 );
- }
- else
- {
- SET_AX( context, 0x00ff );
- SET_CFLAG(context);
- }
- }
- break;
-
- case 0x03: /* Get Extended free space on drive */
- case 0x04: /* Set DPB for formatting */
- case 0x05: /* extended absolute disk read/write */
- FIXME("Unimplemented FAT32 int32 function %04x\n", AX_reg(context));
- SET_CFLAG(context);
- SET_AL( context, 0 );
- break;
- }
-
- break;
-
-
- case 0xdc: /* CONNECTION SERVICES - GET CONNECTION NUMBER */
- case 0xea: /* NOVELL NETWARE - RETURN SHELL VERSION */
- break;
-
default:
INT_BARF( context, 0x21 );
break;
More information about the wine-patches
mailing list