⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 int21.c

📁 freedos32的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* INT 21h handler for the FreeDOS-32 DPMI Driver * Copyright (C) 2001-2005  Salvatore ISAJA * * This file "int21.c" is part of the FreeDOS-32 DPMI Driver (the Program). * * The Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * The Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with the Program; see the file GPL.txt; if not, write to * the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *//* TODO: We should provide some mechanism for installing new fake         interrupt handlers (like this INT 21h handler), with the            possibility of recalling the old one.*/#include <ll/i386/hw-data.h>#include <ll/i386/string.h>#include <kernel.h>#include <filesys.h>#include <errno.h>#include <stubinfo.h>#include <logger.h>#include <fd32time.h>#include "rmint.h"#define DOS_API_INPUT_IS_UTF8 1#if !DOS_API_INPUT_IS_UTF8 #include <unicode/unicode.h> #include <nls/nls.h> struct nls_operations *current_cp;#endif#if defined(__GNUC__) && !defined(restrict) #define restrict __restrict__#endif/* Define the __DEBUG__ symbol in order to activate log output *///#define __DEBUG__#ifdef __DEBUG__ #define LOG_PRINTF(s) fd32_log_printf s#else #define LOG_PRINTF(s)#endif#define FAR2ADDR(seg, off) (((DWORD) seg << 4) + (DWORD) off)/* The current PSP is needed for the pointer to the DTA */extern struct psp *current_psp;int use_lfn;/* Parameter block for the dos_exec call, see INT 21h AH=4Bh */typedef struct{  WORD  Env;  WORD arg_offs;  WORD arg_seg;  DWORD Fcb1;  DWORD Fcb2;  DWORD Res1;  DWORD Res2;}__attribute__ ((packed)) ExecParams;/* DOS return code of the last executed program */static WORD dos_return_code;/* Data structure for INT 21 AX=7303h                   *//* Windows95 - FAT32 - Get extended free space on drive */typedef struct{  WORD  Size;            /* Size of the returned structure (this one)  */  WORD  Version;         /* Version of this structure (desired/actual) */  /* The following are *with* adjustment for compression */  DWORD SecPerClus;      /* Sectors per cluster               */  DWORD BytesPerSec;     /* Bytes per sector                  */  DWORD AvailClus;       /* Number of available clusters      */  DWORD TotalClus;       /* Total number of clusters on drive */  /* The following are *without* adjustment for compression */  DWORD RealSecPerClus;  /* Number of sectors per cluster     */  DWORD RealBytesPerSec; /* Bytes per sector                  */  DWORD RealAvailClus;   /* Number of available clusters      */  DWORD RealTotalClus;   /* Total number of clusters on drive */  BYTE  Reserved[8];}__attribute__ ((packed)) ExtDiskFree;/* DOS error codes (see RBIL table 01680) */#define DOS_ENOTSUP   0x01 /* function number invalid */#define DOS_ENOENT    0x02 /* file not found */#define DOS_ENOTDIR   0x03 /* path not found */#define DOS_EMFILE    0x04 /* too many open files */#define DOS_EACCES    0x05 /* access denied */#define DOS_EBADF     0x06 /* invalid handle */#define DOS_ENOMEM    0x08 /* insufficient memory */#define DOS_EMEMBLK   0x09 /* memory block address invalid */#define DOS_EFTYPE    0x0B /* format invalid */#define DOS_EDATA     0x0D /* data invalid */#define DOS_ENOTBLK   0x0F /* invalid drive */#define DOS_EXDEV     0x11 /* not same device */#define DOS_ENOMOREF  0x12 /* no more files */#define DOS_EROFS     0x13 /* disk write-protected */#define DOS_EUNIT     0x14 /* unknown unit */#define DOS_ENOMEDIUM 0x15 /* drive not ready */#define DOS_EIO       0x1F /* general failure */#define DOS_ENOSPC    0x27 /* insufficient disk space */#define DOS_EEXIST    0x50 /* file exists */#define DOS_EUNKNOWN  0x64 /* unknown error */#define DOS_EBUFSMALL 0x7A /* buffer too small to hold return data */#define DOS_EINVAL    0xA0 /* bad arguments */#define DOS_ENOLCK    0xB4 /* lock count has been exceeded */#define DOS_ENOEXEC   0xC1 /* bad EXE format *//* Lookup table to convert FD32 errno codes to DOS error codes *//* TODO: Fine tune the mapping using the DJGPP one as a reference */static const BYTE errno2dos[] = {/*   0 */ 0x00,         DOS_EUNKNOWN, DOS_ENOENT,   DOS_EUNKNOWN,/*   4 */ DOS_EUNKNOWN, DOS_EIO,      DOS_EUNIT,    DOS_EUNKNOWN,/*   8 */ DOS_ENOEXEC,  DOS_EBADF,    DOS_EUNKNOWN, DOS_EUNKNOWN,/*  12 */ DOS_ENOMEM,   DOS_EACCES,   DOS_EMEMBLK,  DOS_EUNIT,/*  16 */ DOS_EUNKNOWN, DOS_EEXIST,   DOS_EXDEV,    DOS_EUNIT,/*  20 */ DOS_ENOTDIR,  DOS_EACCES,   DOS_EINVAL,   DOS_EMFILE,/*  24 */ DOS_EMFILE,   DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EACCES,/*  28 */ DOS_ENOSPC,   DOS_EUNKNOWN, DOS_EROFS,    DOS_EUNKNOWN,/*  32 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN,/*  36 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN,/*  40 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN,/*  44 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_ENOLCK,   DOS_EUNKNOWN,/*  48 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN,/*  52 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_ENOTSUP,  DOS_EUNKNOWN,/*  56 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN,/*  60 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN,/*  64 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN,/*  68 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN,/*  72 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN,/*  76 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EFTYPE,/*  80 */ DOS_EUNKNOWN, DOS_EBADF,    DOS_EUNKNOWN, DOS_EUNKNOWN,/*  84 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN,/*  88 */ DOS_ENOTSUP,  DOS_EMFILE,   DOS_EACCES,   DOS_EBUFSMALL,/*  92 */ DOS_EACCES,   DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_ENOTSUP,/*  96 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN,/* 100 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN,/* 104 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN,/* 108 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN,/* 112 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN,/* 116 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN,/* 120 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN,/* 124 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN,/* 128 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EUNKNOWN,/* 132 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_ENOTSUP,  DOS_ENOMEDIUM,/* 136 */ DOS_EUNKNOWN, DOS_EUNKNOWN, DOS_EDATA};/* Converts a FD32 return code (< 0 meaning error) * to a DOS return status in the specified register set. * - on error: carry flag set, error (positive) in AX * - on success: carry flag clear */static void res2dos(int res, union rmregs *r){	LOG_PRINTF(("INT 21h - res=%i\n", res));	RMREGS_CLEAR_CARRY;	if (res < 0)	{		res = -res;		RMREGS_SET_CARRY;		r->x.ax = DOS_EUNKNOWN;		if (res < sizeof(errno2dos)) r->x.ax = errno2dos[res];	}}/* Converts a DOS open action (see RBIL table 01770) to a libc mode. */static int parse_open_action(int dos_action){	int action = 0;	if (dos_action & 0x10) action |= O_CREAT;	switch (dos_action & ~0x10)	{		case 0x00: action |= O_EXCL; break;		case 0x01: break;		case 0x02: action |= O_TRUNC; break;		default: action = -EINVAL;	}	return action;}/* Converts a path name from DOS API to UTF-8 using no more than "size" bytes. * Forward slashes '/' are converted to back slashes '\'. * Returns 0 on success, or a negative error. */static int fix_path(char *restrict dest, const char *restrict source, size_t size){	#if DOS_API_INPUT_IS_UTF8	char c;	while (*source)	{		if (!size) return -ENAMETOOLONG;		c = *(source++);		if (c == '/') c = '\\';		*(dest++) = c;	}	#else	int res = 0;	wchar_t wc;	while (*source)	{		res = current_cp->mbtowc(&wc, source, NLS_MB_MAX_LEN);		if (res < 0) return res;		source += res;		if (wc == (wchar_t) '/') wc = (wchar_t) '\\';		res = unicode_wctoutf8(dest, wc, size);		if (res < 0) return res;		dest += res;		size -= res;			}	#endif	if (!size) return -ENAMETOOLONG;	*dest = 0;	return 0;}/* Sub-handler for DOS services "Get/set file's time stamps" * INT 21h AH=57h (BX=file handle, AL=action). */static inline void get_and_set_time_stamps(union rmregs *r){	fd32_fs_attr_t a;	int res;	a.Size = sizeof(fd32_fs_attr_t);	switch (r->h.al)	{		/* Get last modification date and time */		case 0x00:			/* TODO: MS-DOS returns date and time of opening for char devices */			res = fd32_get_attributes(r->x.bx, &a);			if (res >= 0)			{				r->x.cx = a.MTime;				r->x.dx = a.MDate;			}			break;		/* Set last modification date and time */		case 0x01:			res = fd32_get_attributes(r->x.bx, &a);			if (res >= 0)			{				a.MTime = r->x.cx;				a.MDate = r->x.dx;				res = fd32_set_attributes(r->x.bx, &a);			}			break;		/* Get last access date and time */		case 0x04:			res = fd32_get_attributes(r->x.bx, &a);			if (res >= 0)			{				r->x.dx = a.ADate;				r->x.cx = 0x0000; /* FAT has not the last access time */			}			break;		/* Set last access date and time */		case 0x05:			if (r->x.cx != 0x0000)			{				/* FAT has not the last access time */				res = -EINVAL;				break;			}			res = fd32_get_attributes(r->x.bx, &a);			if (res >= 0)			{				a.ADate = r->x.dx;				res = fd32_set_attributes(r->x.bx, &a);			}			break;		/* Get creation date and time */		case 0x06:			res = fd32_get_attributes(r->x.bx, &a);			if (res >= 0)			{				r->x.dx = a.CDate;				r->x.cx = a.CTime;				r->x.si = a.CHund;			}			break;		/* Set creation date and time */		case 0x07:			res = fd32_get_attributes(r->x.bx, &a);			if (res >= 0)			{				a.CDate = r->x.dx;				a.CTime = r->x.cx;				a.CHund = r->x.si;				res = fd32_set_attributes(r->x.bx, &a);			}			break;		/* Invalid subfunctions */		default:			r->h.al = 0xFF; /* Yet another convention */			RMREGS_SET_CARRY;			return;	}	res2dos(res, r);}/* Sub-handler for DOS service "Get/set file's attributes" * INT 21h AH=43h (DS:DX->ASCIZ file name, AL=action). */static inline void dos_get_and_set_attributes(union rmregs *r){	char fn[FD32_LFNPMAX];	fd32_fs_attr_t a;	int fd;	int res = fix_path(fn, (const char *) FAR2ADDR(r->x.ds, r->x.dx), sizeof(fn));	if (res < 0)	{		res2dos(res, r);		return;	}	fd = fd32_open(fn, O_RDONLY, FD32_ANONE, 0, NULL);	if (fd < 0) /* It could be a directory... */		fd = fd32_open(fn, O_RDONLY | O_DIRECTORY, FD32_ANONE, 0, NULL);	if (fd < 0)	{		res2dos(fd, r);		return;	}	a.Size = sizeof(fd32_fs_attr_t);	switch (r->h.al)	{		/* Get file attributes */		case 0x00:			LOG_PRINTF(("INT 21h - Getting attributes of \"%s\"\n", fn));			res = fd32_get_attributes(fd, &a);			if (res >= 0)			{				r->x.cx = a.Attr;				r->x.ax = r->x.cx; /* DR-DOS 5.0 */			}			break;		/* Set file attributes */		case 0x01:			/* FIXME: Should close the file if currently open in sharing-compat			 *        mode, or generate a sharing violation critical error in			 *        the file is currently open.			 * Mah! Would that be true with the new things? Mah...			 */			LOG_PRINTF(("INT 21h - Setting attributes of \"%s\" to %04x\n", fn, r->x.cx));			res = fd32_get_attributes(fd, &a);			if (res < 0) break;			/* Volume label and directory attributes cannot be changed.			 * To change the other attributes bits of a directory the directory			 * flag must be clear, though it will be set after this call.			 */			if ((r->x.cx & (FD32_AVOLID | FD32_ADIR)) || (a.Attr == FD32_AVOLID))			{				res = -EACCES;				break;			}			a.Attr = r->x.cx;			if (a.Attr & FD32_ADIR) a.Attr = r->x.cx | FD32_ADIR;			res = fd32_set_attributes(fd, &a);			break;		/* Invalid subfunctions */		default:			fd32_close(fd);			r->h.al = 0xFF; /* Yet another convention */			RMREGS_SET_CARRY;			return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -