home *** CD-ROM | disk | FTP | other *** search
- /*
- LDDPMI.C -- undocumented DOS call from DPMI
-
- sample output:
- in protected mode
- Real mode DOS List Of Lists = 028E:0026
- Protected DOS List Of Lists = 00AD:0026
- LASTDRIVE=E
-
- cl -AS lddpmi.c
- */
-
- #ifndef M_I86SM
- #error Requires Microsoft C small model
- #endif
-
- #include <stdlib.h>
- #include <stdarg.h>
- #include <stdio.h>
- #include <dos.h>
-
- #define ABSADDR(seg, ofs) \
- ((((unsigned long) seg) << 4) + ((ofs) & 0xFFFF))
-
- #pragma pack(1)
-
- typedef struct {
- unsigned long edi, esi, ebp, reserved, ebx, edx, ecx, eax;
- unsigned flags, es, ds, fs, gs, ip, cs, sp, ss;
- } RMODE_CALL;
-
- typedef struct {
- unsigned accessed : 1;
- unsigned read_write : 1;
- unsigned conf_exp : 1;
- unsigned code : 1;
- unsigned xsystem : 1;
- unsigned dpl : 2;
- unsigned present : 1;
- } ACCESS;
-
- typedef struct {
- unsigned limit;
- unsigned addr_lo;
- unsigned char addr_hi;
- ACCESS access;
- unsigned reserved;
- } DESCRIPTOR;
-
- typedef enum { FALSE, TRUE } BOOL;
-
- BOOL dpmi_rmode_intr(unsigned intno, unsigned flags,
- unsigned copywords, RMODE_CALL far *rmode_call);
-
- void dos_exit(unsigned err)
- {
- _asm mov al, err
- _asm mov ah, 04ch
- _asm int 21h
- }
-
- void pmode_putchar(int c)
- {
- static RMODE_CALL r;
- static RMODE_CALL *pr = (void *) 0;
- if (! pr)
- {
- pr = &r;
- memset(pr, 0, sizeof(RMODE_CALL));
- r.eax = 0x0200;
- }
- r.edx = c;
- dpmi_rmode_intr(0x21, 0, 0, pr);
- }
-
- void pmode_puts(char *s)
- {
- while (*s)
- {
- pmode_putchar(*s);
- s++;
- }
- pmode_putchar(0x0d);
- pmode_putchar(0x0a);
- }
-
- void cdecl pmode_printf(const char *fmt, ...)
- {
- char buf[128], *s=buf;
- va_list marker;
- va_start(marker, fmt);
- vsprintf(buf, fmt, marker);
- va_end(marker);
- while (*s)
- pmode_putchar(*s++);
- }
-
- void fail(char *s) { puts(s); exit(1); }
- void pmode_fail(char *s) { pmode_puts(s); dos_exit(1); }
-
- /* Determines if DPMI is present and, if so, switches into
- protected mode */
- BOOL dpmi_init(void)
- {
- void (far *dpmi)();
- unsigned hostdata_seg, hostdata_para, dpmi_flags;
- _asm {
- mov ax, 1687h ; test for DPMI presence
- int 2Fh
- and ax, ax
- jnz nodpmi ; if (AX == 0) DPMI is present
- mov dpmi_flags, bx
- mov hostdata_para, si ; paras for DPMI host private data
- mov dpmi, di
- mov dpmi+2, es ; DPMI protected-mode switch entry point
- jmp short gotdpmi
- }
- nodpmi:
- return FALSE;
- gotdpmi:
- if (_dos_allocmem(hostdata_para, &hostdata_seg) != 0)
- pmode_fail("can't allocate memory");
-
- /* enter protected mode */
- _asm {
- mov ax, hostdata_seg
- mov es, ax
- mov ax, dpmi_flags
- }
- (*dpmi)();
-
- return TRUE;
- }
-
- /* Performs a real-mode interrupt from protected mode */
- BOOL dpmi_rmode_intr(unsigned intno, unsigned flags,
- unsigned copywords, RMODE_CALL far *rmode_call)
- {
- if (flags) intno |= 0x100;
- _asm {
- push di
- push bx
- push cx
- mov ax, 0300h ; simulate real-mode interrupt
- mov bx, intno ; interrupt number, flags
- mov cx, copywords; ; words to copy from pmode to rmode stack
- les di, rmode_call ; ES:DI = address of rmode call struct
- int 31h ; call DPMI
- jc error
- mov ax, 1 ; return TRUE
- jmp short done
- error: mov ax, 0 ; return FALSE
- done: pop cx
- pop bx
- pop di
- }
- }
-
- /* Allocates a single protected-mode LDT selector */
- unsigned dpmi_sel(void)
- {
- _asm {
- mov ax, 0 ; Allocate LDT Descriptors
- mov cx, 1 ; allocate just one
- int 31h ; call DPMI
- jc err
- jmp short done ; AX holds new LDT selector
- err: mov ax, 0 ; failed
- done: }
- }
-
- BOOL dpmi_set_descriptor(unsigned pmodesel, DESCRIPTOR far *d)
- {
- _asm {
- push di
- push bx
- mov ax, 000ch ; Set Descriptor
- mov bx, pmodesel ; protected mode selector
- les di, d ; descriptor
- int 31h ; call DPMI
- jc error
- mov ax, 1 ; return TRUE
- jmp short done
- error: mov ax, 0 ; return FALSE
- done: pop di
- pop bx
- }
- }
-
- BOOL dpmi_sel_free(unsigned pmodesel)
- {
- _asm {
- mov ax, 0001h ; Free LDT Descriptor
- mov bx, pmodesel ; selector to free
- int 31h ; call DPMI
- jc error
- mov ax, 1 ; return TRUE
- jmp short done
- error: mov ax, 0 ; return FALSE
- done: }
- }
-
- main(int argc, char *argv[])
- {
- DESCRIPTOR d;
- RMODE_CALL r;
- void far *fp;
- char far *doslist = (char far *) 0;
- unsigned long addr;
- unsigned pmodesel;
- unsigned offset, lastdrv_ofs, lastdrv;
-
- /*
- Determine if DPMI present and, if so, switch
- to protected mode
- */
- if (dpmi_init())
- pmode_puts("now in protected mode");
- else
- fail("DPMI not present");
-
- /*
- Call INT 21h AH=52h (Get DOS List Of Lists)
- */
- memset(&r, 0, sizeof(RMODE_CALL));
- r.eax = 0x5200;
- if (! dpmi_rmode_intr(0x21, 0, 0, &r))
- pmode_fail("DPMI rmode intr failed");
- FP_SEG(doslist) = r.es;
- FP_OFF(doslist) = r.ebx;
- pmode_printf("Real mode DOS List Of Lists = %Fp\r\n", doslist);
-
- /* doslist now holds a real-mode address: in order to address it
- in protected mode, allocate an LDT descriptor and set its
- contents; when done, deallocate the LDT descriptor
- */
- if (! (pmodesel = dpmi_sel()))
- pmode_fail("DPMI can't alloc pmode selector");
- d.limit = 0xFFFF;
- addr = ABSADDR(r.es, 0);
- d.addr_lo = addr & 0xFFFF;
- d.addr_hi = addr >> 16;
- d.access.accessed = 0; /* never been used */
- d.access.read_write = 1; /* read-write */
- d.access.conf_exp = 0; /* not a stack */
- d.access.code = 0; /* data */
- d.access.xsystem = 1; /* not system descriptor */
- fp = (void far *) main;
- d.access.dpl = FP_SEG(fp) & 3; /* protection level */
- d.access.present = 1; /* it's present in memory */
- d.reserved = 0;
- if (! dpmi_set_descriptor(pmodesel, &d))
- pmode_fail("DPMI can't set descriptor");
-
- FP_SEG(doslist) = pmodesel; /* convert to protected-mode address */
- FP_OFF(doslist) = r.ebx;
- pmode_printf("Protected mode DOS List Of Lists = %Fp\r\n", doslist);
-
- /* now have protected-mode selector to DOS List of Lists */
- /* Get LASTDRIVE number, print LASTDRIVE letter */
- lastdrv = doslist[_osmajor==3 && _osminor==0 ? 0x1b : 0x21];
- pmode_printf("LASTDRIVE=%c\r\n", 'A' - 1 + lastdrv);
-
- if (! dpmi_sel_free(pmodesel))
- pmode_fail("DPMI can't free selector");
-
- /* in protected mode, flush output and quit */
- dos_exit(0);
-
- dpmifail:
- pmode_fail("DPMI failure");
- }
-