We help IT Professionals succeed at work.

how to code a DPMI call

damian asked
Medium Priority
Last Modified: 2008-03-06
I need some code about makeing a DPMI 0x0300 call in order
to make a disk read with int13h under WIN 3.1 platform

I tried to use the documentation and it doesn't work at all.

Damian Ionut
Watch Question

Please, explain what's your steps ?
Please, explain what's your steps ?


I need exactly the C coded function  like:

MakeInt13hRead(void far *buffer,int sect,int track,int side);

I allready implemented a general int 13h call function but it doesn't work at all. Maybe it could be a problem with the "void far *buffer" param wich is WINDOWS memory alloc chunk (alocated with DELPHI's new(buffer)
function call, lets say, or with Alloc and Fix etc. ) ... Any further information
nedeed ?? ;)

See ya !
For 16 bit applications the DPMI host automatically handles all
INT nn opcodes to provide BIOS and DOS services transparently.
So you have not the reasons to simulate real mode interrupt.
For checking it I included to my C program following code for reading sector from diskette and it runs OK:
  __asm mov ah,02h
  __asm mov al,01h
  __asm mov ch,00h
  __asm mov cl,01h
  __asm mov dl,00h
  __asm mov dh,01h
  __asm mov bx,seg wrkbuf
  __asm mov es,bx
  __asm mov bx,offset wrkbuf
  __asm int 13h
  __asm mov errcode,ah
According to documentation,Win32 applications cannot communicate with VxDs by the same means that 16-bit can (software interrupts, callbacks, VxD services, etc.) Win32 applications must use
DeviceIOControl interface to communicate with VxDs that support
device I/O calls.


I think you have not tested it ... ;)
I have done it allready ...

Saa ya !
I tested it on QuickC for Windows v.1.0. I could see that diskette drive started work, wrkbuf was filled some information, but I didn't check this information, becouse you sad INT 13h didn't work at all. Of course, I can check it too, but I think
it's not necessary, it's run OK. But if you have done it allready and my code didn't run on your hardware too, you should see the Diskette Parameter Table using INT 1Eh or you can get this address from BIOS directly at 0:0078 If you will have troubles
in this cause too, just E-mail me, I will try to help you :-).

John Mc HaleForensic Computer Examiner, Analyst/Programmer & Database Architect

I have a vested interest in the area that you have asked about. My angle is that I am currently writing a Windows 3.1 utility program to copy diskettes. This requires the use of int13 subfunctions 2,3,4,5, and 0 naturally. I cannot even help you unless I know what angle you are coming from. Specifically, what subfunctions are you interested in? and what are your problems with them? I have had a lot of problems myself and am  working around them one by one. If you  would like to work with me if possible. I know a little about DPMI. Myb e-mail is:


Ok guiz!
Thanx a lot for help, but I found the code on MSDN CD. It is not that easy as it seems.

BTW, with FDD is more easy than HDD... you can use a lot of other functions ...
PS: If you need this code, I'll be glad to share it with you !
See ya
John Mc HaleForensic Computer Examiner, Analyst/Programmer & Database Architect

Sample code for FDD\Win16

Yes please slash.



I'll send you by e-mail ....
BTW ... send me your datas at slash@buc.soros.ro and I'll reply you with the code !!!

See ya !
Here is some code I wrote to do CD-ROM disc access under DPMI and with a small amount of work you should be able to modify it to make your own calls to int13h.

The important points to note are the use of GlobalDosAlloc functions to allocate buffers and the setting up of the dpmi registers. Ignore the pvRequest structure, this is specific to MSCDEX calls for CD-ROM drives.

It compiles under MSVC 1.52 under large memory model.

There may be a problem with line wrap. If you can't work it out give me an e-mail and I will reply with the code in that way.


--- cut here ---
#include <windows.h>
#include <malloc.h>
#include <memory.h>

typedef      struct      _dpmi_regs_ DPMI_REGS;
// Request Header structure. (MSCDEX)
typedef struct
      unsigned char      rhLength;            // length of structure
      unsigned char      rhUnit;                  // minor device
      unsigned char      rhFunction;            //
      unsigned int      rhStatus;            // status return word
      unsigned char      rhReserved[8];      // reserved
      unsigned char      cAddrMode;            // addressing mode
      unsigned long      lTranAddr;            // transfer address
      unsigned int      nSecs;                  // number of sectors to read
      unsigned long      lStartSec;            // start sector
      unsigned char      cMode;                  // data read mode
      unsigned char      cILSize;            // interleave size
      unsigned char      cILSkip;            // interleave skip factor
      } REQSTRC;

struct _dpmi_regs_
      long      ddi;
      long      dsi;
      long      dbp;
      long      zero;
      long      dbx;
      long      ddx;
      long      dcx;
      long      dax;
      WORD      flags;
      WORD      des;
      WORD      dds;
      WORD      dfs;
      WORD      dgs;
      WORD      dip;
      WORD      dcs;
      WORD      dsp;
      WORD      dss;

#define      CARRY_FLAG                  0x01
#define FLAG_DIRECTORY      2

static unsigned int      WinCallRMInt(WORD wInt, DPMI_REGS *pDPMIregs);
static int                  LmReadCDSector(int nDrive, long lSector, void *pvSectorBuffer, int mode);

//      NAME:      CDReadSector
//            Read a single 'sector' from the CD-ROM in drive 'volumeIndex' in cooked
//            mode and put the results into the 'pBuffer'.
//            volumeIndex      The drive number of the CD-ROM drive containing the disc
//                              to be tested where 0 = drive letter 'A'
//            sector            The sector number to read
//            pBuffer            The buffer to put the cooked (2048 bytes) of data into
//            ...                  Return values defined by LmReadCDSector.
//      GLOBALS:
//            none.
int   CDReadSector(int volumeIndex, unsigned long sector, void *pBuffer)
       return LmReadCDSector((int)volumeIndex, sector, pBuffer, 0);

//      NAME:      LmReadCDSector
//            Read a sector from a CD-ROM using the 'Send Device Driver Request, Read long' method
static int LmReadCDSector(int nDrive, long lSector, void *pvSectorBuffer, int mode)
      DPMI_REGS      dpmiregs;
      void            *pvRealModeBuffer;            // Pointer to real mode buffer to hold sector data
      REQSTRC            *pvRequest;                        // Pointer to real mode request buffer
      DWORD       dwGDMemSector;                  // Global DOS memory for sector data
      DWORD            dwGDMemRequest;                  // Global DOS memory for request structure
      int                  nResult;                        // Result from INT 2f function
      int                  retval;                              // Return value from function
      memset(&dpmiregs, 0, sizeof(DPMI_REGS));

      // Allocate DOS memory for reading sectors (and drive list)
      dwGDMemSector = GlobalDosAlloc((DWORD)2352);
      dwGDMemRequest = GlobalDosAlloc((DWORD)sizeof(REQSTRC));

      if (dwGDMemSector == NULL || dwGDMemRequest == NULL)
            retval = 1;
            pvRequest = MAKELP(LOWORD(dwGDMemRequest), 0);
            memset(&dpmiregs, 0, sizeof(DPMI_REGS));
            memset(pvRequest, 0, sizeof(REQSTRC));
            pvRequest->rhLength = sizeof(REQSTRC);
            pvRequest->rhFunction = 128;
            pvRequest->lTranAddr = dwGDMemSector & 0xFFFF0000l;
            pvRequest->nSecs = 1;
            pvRequest->lStartSec = lSector;
            pvRequest->cMode = mode;
            dpmiregs.dax = 0x1510;
            dpmiregs.dcx = (int)nDrive - 1;
            dpmiregs.des = HIWORD(dwGDMemRequest);
            dpmiregs.dbx = 0;

            nResult = WinCallRMInt(0x2f, &dpmiregs);
            if ((nResult == 0) && (!(dpmiregs.flags & CARRY_FLAG)))
                  // Protected mode address
                  pvRealModeBuffer = MAKELP(LOWORD(dwGDMemSector), 0);
                  memcpy(pvSectorBuffer, pvRealModeBuffer, mode ? 2352: 2048);
                  retval = 0;
                  retval = 2;

      if (dwGDMemSector) GlobalDosFree(LOWORD(dwGDMemSector));
      if (dwGDMemRequest) GlobalDosFree(LOWORD(dwGDMemRequest));

#pragma optimize("", off)
//      NAME:      WinCallRMInt
//            Simulate the Real Mode Interrupt by calling the DPMI function 0x0300
static unsigned int WinCallRMInt(WORD wInt, DPMI_REGS *pDPMIregs)
      WORD            wSel;
      WORD            wOff;
      int                  nReturn;

      wSel = SELECTOROF(pDPMIregs);
      wOff = OFFSETOF(pDPMIregs);
      _asm {
            mov            ax, 0x0300
            mov            bx, wInt
            mov            cx, 0
            mov            es, wSel
            mov            di, wOff

            int            0x31
            jc            dpmi_error
            xor            ax, ax                  //      Success.
            mov            nReturn, ax            // Return code
      // Returns: AX == 0 if ok, or DPMI error code
      return nReturn;

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.


Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.