ChangLog: * dlls/winedos/int21.c * msdos/int21.c Move FAT32 functions to winedos nog.
--- 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;