📄 int21.c
字号:
} fd32_close(fd); res2dos(res, r);}/* Sub-handler for LFN service "Extended get/set attributes" * INT 21h AX=7143h (DS:DX->ASCIZ file name, BL=action). */static inline void lfn_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_RDWR, FD32_ANONE, 0, NULL); if (fd < 0) /* It could be a directory... */ fd = fd32_open(fn, O_RDWR | O_DIRECTORY, FD32_ANONE, 0, NULL); if (fd < 0) { res2dos(res, r); return; } a.Size = sizeof(fd32_fs_attr_t); switch (r->h.bl) { /* Get file attributes */ case 0x00: res = fd32_get_attributes(fd, &a); if (res >= 0) r->x.cx = a.Attr; break; /* Set file attributes */ case 0x01: res = fd32_get_attributes(fd, &a); if (res >= 0) { a.Attr = r->x.cx; res = fd32_set_attributes(fd, &a); } break; /* Get physical size of compressed file */ /* case 0x02: Not implemented */ /* Set last modification date and time */ case 0x03: res = fd32_get_attributes(fd, &a); if (res >= 0) { a.MDate = r->x.di; a.MTime = r->x.cx; res = fd32_set_attributes(fd, &a); } break; /* Get last modification date and time */ case 0x04: res = fd32_get_attributes(fd, &a); if (res >= 0) { r->x.di = a.MDate; r->x.cx = a.MTime; } break; /* Set last access date */ case 0x05: /* DI new date in DOS format */ res = fd32_get_attributes(fd, &a); if (res >= 0) { a.ADate = r->x.di; res = fd32_set_attributes(fd, &a); } break; /* Get last access date */ case 0x06: res = fd32_get_attributes(fd, &a); if (res >= 0) r->x.di = a.ADate; break; /* Set creation date and time */ case 0x07: res = fd32_get_attributes(fd, &a); if (res >= 0) { a.CDate = r->x.di; a.CTime = r->x.cx; a.CHund = r->x.si; res = fd32_set_attributes(fd, &a); } break; /* Get creation date and time */ case 0x08: res = fd32_get_attributes(fd, &a); if (res >= 0) { r->x.di = a.CDate; r->x.cx = a.CTime; r->x.si = a.CHund; } break; /* Unsupported or invalid actions */ default: fd32_close(fd); r->x.ax = 0x7100; /* Yet another convention */ RMREGS_SET_CARRY; return; } fd32_close(fd); res2dos(res, r);}/* Sub-handler for Long File Names services * INT 21h AH=71h (AL=function) */static inline void lfn_functions(union rmregs *r){ char fn[FD32_LFNPMAX]; int res; switch (r->h.al) { /* Make directory (DS:DX->ASCIZ directory name) */ case 0x39: res = fix_path(fn, (const char *) FAR2ADDR(r->x.ds, r->x.dx), sizeof(fn)); if (res >= 0) res = fd32_mkdir(fn); break; /* Remove directory (DS:DX->ASCIZ directory name) */ case 0x3A: res = fix_path(fn, (const char *) FAR2ADDR(r->x.ds, r->x.dx), sizeof(fn)); if (res >= 0) res = fd32_rmdir(fn); break; /* Change directory (DS:DX->ASCIZ directory name) */ case 0x3B: res = fix_path(fn, (const char *) FAR2ADDR(r->x.ds, r->x.dx), sizeof(fn)); if (res >= 0) res = fd32_chdir(fn); break; /* Delete file (DS:DX->ASCIZ file name, CL=search attributes, * CL=must-match attributes, SI=use wildcards and attributes [0=no,1=yes]). * FIXME: Parameter in SI not used. */ case 0x41: res = fix_path(fn, (const char *) FAR2ADDR(r->x.ds, r->x.dx), sizeof(fn)); if (res >= 0) res = fd32_unlink(fn, ((DWORD) r->h.ch << 8) + (DWORD) r->h.cl); break; /* Extended get/set file attributes */ case 0x43: lfn_get_and_set_attributes(r); return; /* Get current directory (DL=drive number [0=default, 1=A, etc.], * DS:SI->260-bytes buffer for ASCIZ pathname). * Same as INT 21h AH=47h, but we don't convert to 8.3 the resulting path */ case 0x47: { char drive[2] = "A"; char *dest = (char *) FAR2ADDR(r->x.ds, r->x.si); drive[0] = fd32_get_default_drive(); if (r->h.dl) drive[0] = r->h.dl + 'A' - 1; res = fd32_getcwd(drive, fn); if (res >= 0) { strcpy(dest, fn + 1); /* Skip leading backslash */ /* FIXME: Convert from UTF-8 to OEM */ } break; } /* Find first matching file (DS:DX->ASCIZ file spec, ES:DI->find data record, * CL=allowable attributes, CH=required attributes, SI=date/time format * [0=Windows time, 1=DOS time]). * FIXME: Parameter in SI not used. */ case 0x4E: res = fix_path(fn, (const char *) FAR2ADDR(r->x.ds, r->x.dx), sizeof(fn)); if (res < 0) break; res = fd32_lfn_findfirst(fn, ((DWORD) r->h.ch << 8) + (DWORD) r->h.cl, (fd32_fs_lfnfind_t *) FAR2ADDR(r->x.es, r->x.di)); res2dos(res, r); if (res >= 0) { r->x.ax = (WORD) res; /* The directory handle to continue the search */ /* FIXME: Unicode conversion flags in CX not implemented * bit 0 set if the returned long name contains * underscores for unconvertable Unicode characters * bit 1 set if the returned short name contains * underscores for unconvertable Unicode characters */ r->x.cx = 0; } else if (res == -ENOENT) r->x.ax = DOS_ENOMOREF; return; /* Find next matching file (ES:DI->find data record, BX=directory handle, * SI=date/time format [0=Windows time, 1=DOS time]). * FIXME: Same FIXMEs as case 0x4E. */ case 0x4F: res = fd32_lfn_findnext(r->x.bx, 0, (fd32_fs_lfnfind_t *) FAR2ADDR(r->x.es, r->x.di)); res2dos(res, r); if (res >= 0) r->x.cx = 0; else if (res == -ENOENT) r->x.ax = DOS_ENOMOREF; return; /* Rename of move file (DS:DX->ASCIZ old name, ES:DI->ASCIZ new name) */ case 0x56: { char newfn[FD32_LFNPMAX]; res = fix_path(fn, (const char *) FAR2ADDR(r->x.ds, r->x.dx), sizeof(fn)); if (res < 0) break; res = fix_path(newfn, (const char *) FAR2ADDR(r->x.es, r->x.di), sizeof(newfn)); if (res >= 0) res = fd32_rename(fn, newfn); break; } /* Truename (CL=subfunction) */ case 0x60: /* FIXME: Only subservice 01h "Get short (8.3) filename for file" is implemented */ if (r->h.cl != 0x01) { res = -ENOTSUP; break; } /* CH=SUBST expansion flag (ignored), 80h to not resolve SUBST * DS:SI->ASCIZ long file name or path * ES:DI->64-bytes buffer for short path name */ res = fix_path(fn, (const char *) FAR2ADDR(r->x.ds, r->x.si), sizeof(fn)); if (res >= 0) res = fd32_sfn_truename((char *) FAR2ADDR(r->x.es, r->x.di), fn); break; /* Create or open file (BX=access mode and sharing flags, CX=attributes * for creation, DX=action, DS:SI->ASCIZ file name, DI=numeric tail hint). */ case 0x6C: { int action; res = parse_open_action(r->x.dx); if (res < 0) break; action = res; res = fix_path(fn, (const char *) FAR2ADDR(r->x.ds, r->x.si), sizeof(fn)); if (res < 0) break; res = fd32_open(fn, action | (DWORD) r->x.bx, r->x.cx, r->x.di, &action); res2dos(res, r); if (res >= 0) { r->x.ax = (WORD) res; /* Returned handle */ r->x.cx = (WORD) action; /* Action taken */ } return; } /* Get volume informations (DS:DX->ASCIZ root directory name, * ES:DI->buffer to store the file system name, CX=size of the * buffer pointed by ES:DI). */ case 0xA0: { fd32_fs_info_t fsi; res = fix_path(fn, (const char *) FAR2ADDR(r->x.ds, r->x.dx), sizeof(fn)); if (res < 0) break; fsi.Size = sizeof(fd32_fs_info_t); fsi.FSNameSize = r->x.cx; fsi.FSName = (char *) FAR2ADDR(r->x.es, r->x.di); res = fd32_get_fsinfo(fn, &fsi); if (res >= 0) { r->x.bx = fsi.Flags; r->x.cx = fsi.NameMax; r->x.dx = fsi.PathMax; } break; } /* "FindClose" - Terminate directory search (BX=directory handle) */ case 0xA1: res = fd32_lfn_findclose(r->x.bx); break; /* Unsupported or invalid actions */ default: r->x.ax = 0x7100; /* Yet another convention */ RMREGS_SET_CARRY; return; } res2dos(res, r);}/* INT 21h handler for DOS file system services (AH=function) */void int21_handler(union rmregs *r){ int res; long long int res64; char fn[FD32_LFNPMAX]; switch (r->h.ah) { /* DOS 1+ - Direct character input, without echo */ case 0x07: { int tmp; /* Perform 1-byte read from the stdin, file handle 0. 1. Save the old mode of stdin 2. Set the stdin to the raw mode without echo 3. Read 1 byte from stdin and restore the old mode This procedure is very alike when doing on the Win32 platform */ /* This call doesn't check for Ctrl-C or Ctrl-Break. */ fd32_get_attributes(0, &tmp); res = 0; /* Res used to set the attributes only once */ fd32_set_attributes(0, &res); res = fd32_read(0, &(r->h.al), 1); fd32_set_attributes(0, &tmp); /* Return the character in AL */ /* TODO: 1. Get rid of the warning: passing arg 2 of `fd32_get_attributes' from incompatible pointer type, maybe using another system call? 2. from RBIL: if the interim console flag is set (see AX=6301h), partially-formed double-byte characters may be returned */ return; } /* DOS 1+ - Set default drive (DL=drive, 0=A, etc.) */ case 0x0E: LOG_PRINTF(("INT 21h - Set default drive to %02x\n", r->h.dl)); res = fd32_set_default_drive(r->h.dl + 'A'); if (res >= 0) return; { /* Return the number of potentially valid drive letters in AL */ r->h.al = (BYTE) res; RMREGS_CLEAR_CARRY; } /* No error code is documented. Check this. */ return; /* DOS 1+ - Get default drive (in AL, 0=A, etc.) */ case 0x19: r->h.al = fd32_get_default_drive() - 'A'; LOG_PRINTF(("INT 21h - Get default drive: %02x\n", r->h.al)); RMREGS_CLEAR_CARRY; return; /* DOS 1+ - Set Disk Transfer Area address (DS:DX->new DTA) */ case 0x1A: LOG_PRINTF(("INT 21h - Set Disk Transfer Area Address: %04x:%04x\n", r->x.ds, r->x.dx)); current_psp->dta = (void *) FAR2ADDR(r->x.ds, r->x.dx); return; /* DOS 1+ - GET SYSTEM DATE */ case 0x2A: { fd32_date_t d; fd32_get_date(&d); r->x.cx = d.Year; r->h.dh = d.Mon; r->h.dl = d.Day; r->h.al = d.weekday; RMREGS_CLEAR_CARRY; return; } /* DOS 1+ - GET SYSTEM TIME */ case 0x2C: { fd32_time_t t; fd32_get_time(&t); r->h.ch = t.Hour; r->h.cl = t.Min; r->h.dh = t.Sec; r->h.dl = t.Hund; RMREGS_CLEAR_CARRY; return; } /* DOS 2+ - Get Disk Transfer Area address (ES:BX <- current DTA) */ case 0x2F: r->x.es = (DWORD) current_psp->dta >> 4; r->x.bx = (DWORD) current_psp->dta & 0xF; LOG_PRINTF(("INT 21h - Get Disk Transfer Area Address: %04x:%04x\n", r->x.es, r->x.bx)); return; /* DOS 2+ - Get DOS version, subject to modification by SETVER * (AL=what to return in BH: 0=OEM number, 1=version flag). */ case 0x30: LOG_PRINTF(("INT 21h - Get DOS version\n")); if (r->h.al) r->h.bh = 0x00; /* DOS is not in ROM (bit 3) */ else r->h.bh = 0xFD; /* We claim to be FreeDOS */ /* Set the 24-bit User Serial Number to zero as we don't use it */ r->h.bl = 0; r->x.cx = 0; r->x.ax = 0x0A07; /* We claim to be 7.10 */ RMREGS_CLEAR_CARRY; return; /* DOS 2+ AL=06h - Get ture DOS version */ case 0x33: LOG_PRINTF(("INT 21h - Get true DOS version\n")); if (r->h.al == 0x06) { r->x.bx = 0x0A07; /* We claim to be 7.10 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -