Solved

Delphi: Int 2F Abs Reed  CD

Posted on 1997-05-25
6
354 Views
Last Modified: 2013-12-03
Win32 Int 2F - Absolute Disk Reed.

At Microsoft.com i have learned that i must use a 16bit DLL.

I Need an exampel on how to do - or a place were i can find a allready made int 2F DLL!
0
Comment
Question by:frj052597
  • 3
  • 3
6 Comments
 
LVL 23

Accepted Solution

by:
chensu earned 200 total points
ID: 1397648
I answered a similar question under this topic area. I copied the following article from KB: Win32.

            How Win32 Applications Can Read CD-ROM Sectors in Windows 95

            PSS ID Number: Q137813
            Article last modified on 10-09-1995
             
            4.00
             
            WINDOWS
             

            ---------------------------------------------------------------------
            The information in this article applies to:
             
             - Microsoft Win32 Application Programming Interface (API) included with:
               Microsoft Windows 95 version 4.0
            ---------------------------------------------------------------------
             
            SUMMARY
            =======
             
            Some Win32 applications, such as multimedia applications and games, need to
            read sectors directly from compact discs to implement custom access or read
            caching to optimize CD-ROM access for specific purposes. This article
            provides information and example code that demonstrates how Win32-based
            applications can read sectors from compact discs in Windows 95.
             
            MORE INFORMATION
            ================
             
            The Windows 95 Compact Disc File System (CDFS) is a protected-mode CD-ROM
            driver that implements the V86-mode MSCDEX Interrupt 2Fh functions as its
            sole application-callable interface. This interface allows it to replace
            real-mode CD-ROM drivers and MSCDEX.EXE and still be completely compatible
            with existing applications for MS-DOS and Windows 3.x. In fact,
            applications for MS-DOS and Windows 3.x will not be able to tell the
            difference between CDFS and MSCDEX.EXE.
             
            Windows 95 provides an interface for Win32-based applications to read
            sectors from compact discs; this interface differs substantially from that
            provided by Windows NT. Unlike Windows NT, which uses CreateFile() and
            ReadFile() to read sectors from compact discs, Windows 95 does not provide
            a Win32 API function for reading sectors. Instead, Win32-based applications
            running under Windows 95 must use an indirect method that involves thunking
            to a 16-bit DLL that calls MSCDEX functions.
             
            The MSCDEX interface that CDFS provides is callable only in V86-mode, so
            Win32-based applications must thunk to a 16-bit DLL, and the 16-bit DLL
            must use the DOS Protected Mode Interface (DPMI) Simulate Real Mode
            Interrupt function to call MSCDEX Interrupt 2Fh functions. The Win32-based
            application must pass a buffer to the 16-bit DLL by using the thunk. Inside
            the thunk, the 16-bit DLL obtains the sector data from MSCDEX, copies it
            into the Win32-based application's buffer, and returns to the Win32-based
            application.
             
            The following code demonstrates how to read sectors from a compact disc
            using the method described above. Because the code implements a flat thunk,
            it is divided into three sections:
             
             - Code that resides in a Win32 DLL (the 32-bit side of the thunk).
             
             - Code that resides in the thunk script.
             
             - Code that resides in the 16-bit DLL that actually calls MSCDEX.
             
            //--------------------------------------------------------------------
            // Code inside the Win32 DLL (the 32-bit side of the thunk)
            // ReadSectorsFromCD() is exported by the DLL so that it can be called
            // by Win32-based applications.
             
            #include <windows.h>
             
            #define CD_SECTOR_SIZE 2048
             
            __declspec(dllexport)
            BOOL WINAPI ReadSectorsFromCD (BYTE bDrive,
                DWORD dwStartSector,
                WORD wSectors,
                LPBYTE lpBuff);
             
            // Prototype for thunk function in 16-bit DLL.
            BOOL FAR PASCAL ReadCDRomSectors (BYTE bDrive,
                DWORD dwStartSector,
                WORD wSectors,
                LPBYTE lpBuffer);
             
            /*-------------------------------------------------------------------
              ReadSectorsFromCD()
             
              Calls the thunked function, ReadCDRomSectors(). This function is
              exported by the Win32 DLL and thus is callable from Win32-based
              applications.
             
              Parameters:
             
                bDrive
                Drive letter of CD-ROM drive to read from. Specified as
                a character in the range 'A', 'B', 'C', ..., 'Z'. May be
                upper- or lower-case.
             
                dwStartSector
                First sector to read.
             
                wSectors
                Number of sectors to read.
             
                lpBuffer
                Buffer to contain sector data. Must be large enough to
                accomodate all sectors being read. Because this buffer is
                provided to the 16-bit DLL via a thunk, its maximum
                length is limited to 64K.
             
              Example use:
                // Read 5 sectors from CD-ROM drive E: starting at sector 16.
                fResult = ReadSectorsFromCD ('E', 16, 5, lpBuff);
             
              Return Value
                Returns TRUE if successful, or FALSE if an error occurred
                in reading or if a parameter was invalid.
            -------------------------------------------------------------------*/
             
            __declspec(dllexport)
            BOOL WINAPI ReadSectorsFromCD (BYTE bDrive,
                DWORD dwStartSector,
                WORD wSectors,
                LPBYTE lpBuff)
            {
               // Call 16-bit DLL to read sectors via a 32->16 thunk
               return ReadCDRomSectors (bDrive, dwStartSector, wSectors, lpBuff);
            }
             
            //--------------------------------------------------------------------
            // Contents of the thunk script
             
            enablemapdirect3216 = true;
             
            typedef unsigned short WORD;
            typedef unsigned long DWORD;
            typedef unsigned char BYTE, *LPBYTE;
            typedef bool BOOL;
             
            BOOL ReadCDRomSectors (BYTE bDrive,
                DWORD dwStartSector,
                WORD wSectors,
                LPBYTE lpBuffer)
            {
               lpBuffer = inout;
            }
             
            //--------------------------------------------------------------------
            // Code inside the 16-bit DLL. This code implements the 16-bit side of
            // the thunk, and is where the calls to MSCDEX are made to read
            // sectors from a compact disc.
             
            #include <windows.h>
            #include <string.h>
            #include <ctype.h>
             
            // Cooked-mode sector size in bytes
            #define CD_SECTOR_SIZE 2048
             
            // Maximum sector buffer size in bytes
            #define MAX_BUFFER_LENGTH 65536
             
            // Maximum muber of sectors for each read request
            #define MAX_CD_SECTORS_TO_READ ((MAX_BUFFER_LENGTH) / \
                (CD_SECTOR_SIZE))
             
            // Processor flags masks -- use for testing wFlags member of RMCS
            #define CARRY_FLAG 0x0001
             
            // Real-mode call structure for making DPMI Simulate Real Mode
            // Interrupt calls.
            typedef struct tagRMCS
            {
               DWORD edi, esi, ebp, RESERVED, ebx, edx, ecx, eax;
               WORD wFlags, es, ds, fs, gs, ip, cs, sp, ss;
            } RMCS, FAR* LPRMCS;
             
            BOOL FAR PASCAL __export ReadCDRomSectors (BYTE bDrive,
                DWORD dwStartSector,
                WORD wSectors,
                LPBYTE lpBuffer);
             
            BOOL FAR PASCAL MSCDEX_ReadSector (BYTE bDrive,
                DWORD dwStartSector,
                LPBYTE RMlpBuffer);
             
            BOOL FAR PASCAL SimulateRM_Int (BYTE bIntNum, LPRMCS lpCallStruct);
            void FAR PASCAL BuildRMCS (LPRMCS lpCallStruct);
             
            /*-------------------------------------------------------------------
              ReadCDRomSectors()
             
              Reads a specified number of sectors from a CD-ROM.
             
              Parameters:
             
                bDrive
                Drive letter of CD-ROM drive to read from. Specified as
                a character in the range 'A', 'B', 'C', ..., 'Z'. May be
                upper- or lower-case.
             
                dwStartSector
                First sector to read.
             
                wSectors
                Number of sectors to read.
             
                lpBuffer
                Buffer to contain sector data. Must be large enough to
                accomodate all sectors being read. Since this buffer is
                provided by the calling Win32 application, no more than
                the first 64K bytes will be used.
             
              Return Value
                Returns TRUE if successful, or FALSE if an error occurred
                in reading or if a parameter was invalid.
            -------------------------------------------------------------------*/
             
            BOOL FAR PASCAL __export ReadCDRomSectors (BYTE bDrive,
                DWORD dwStartSector,
                WORD wSectors,
                LPBYTE lpBuffer)
            {
               BOOL fResult;
               DWORD cbOffset;
               DWORD i;
               DWORD gdaBuffer; // Return value of GlobalDosAlloc().
               LPBYTE RMlpBuffer; // Real-mode buffer pointer
               LPBYTE PMlpBuffer; // Protected-mode buffer pointer
             
               // Convert drive letter into drive number for MSCDEX call.
               bDrive = toupper(bDrive) - 'A';
             
               /*
                Validate parameters:
                bDrive must be between 0 and 25, inclusive.
                lpBuffer must not be NULL.
                wSectors must be between 1 and the maximum number of
                sectors that can fit into a 64K buffer, inclusive.
               */
               if (bDrive > 25 || !lpBuffer)
                return FALSE;
             
               if (!wSectors || (wSectors > MAX_CD_SECTORS_TO_READ))
                return FALSE;
             
               /*
                Allocate buffer for MSCDEX call. This buffer must be below 1MB
                because the MSCDEX function will be called using DPMI. Like real-
                mode MSCDEX.EXE, CDFS implements the MSCDEX API as V86-mode
                Interrupt 2Fh functions.
             
                Free memory below 1MB is relatively scarce, so allocating a
                small sector buffer increases the chances that it can be
                allocated no matter how many other applications and MS-DOS
                device drivers are running. Also, a small sector buffer leaves
                more memory for other applications to use.
               */
               gdaBuffer = GlobalDosAlloc (CD_SECTOR_SIZE);
             
               if (!gdaBuffer)
                return FALSE;
             
               RMlpBuffer = (LPBYTE)MAKELONG(0, HIWORD(gdaBuffer));
               PMlpBuffer = (LPBYTE)MAKELONG(0, LOWORD(gdaBuffer));
             
               // Call MSCDEX to read each sector.
               for (i = cbOffset = 0;
                i < wSectors;
                i++, cbOffset += CD_SECTOR_SIZE)
                {
                if (fResult = MSCDEX_ReadSector (bDrive,
                dwStartSector + i,
                RMlpBuffer))
                _fmemcpy (lpBuffer + cbOffset, PMlpBuffer, CD_SECTOR_SIZE);
                else
                break;
                }
             
               GlobalDosFree (LOWORD(gdaBuffer));
             
               return (fResult);
            }
             
            /*-------------------------------------------------------------------
              MSCDEX_ReadSector()
             
              Calls MSCDEX to read a single sector from a CD-ROM compact disc.
             
              Parameters:
             
                bDrive
                Drive number of CD-ROM drive to read from. Expected to be
                a number in the following series: 0 = A, 1 = B, 2 = C, etc.
             
                dwStartSector
                First sector of read.
             
                RMlpBuffer
                Real-mode segment:offset pointer to a buffer that will receive
                sector data. Must be large enough to accomodate a single
                sector in cooked mode.
             
              Return Value
                Returns TRUE if successful, or FALSE if an error occurred in
                reading.
            -------------------------------------------------------------------*/
             
            BOOL FAR PASCAL MSCDEX_ReadSector (BYTE bDrive,
                DWORD dwStartSector,
                LPBYTE RMlpBuffer)
            {
               RMCS callStruct;
               BOOL fResult;
             
               /*
                Prepare DPMI Simulate Real Mode Interrupt call structure with
                the register values used to make the MSCDEX Absolute read call.
                Then, call MSCDEX using DPMI and check for errors in both the DPMI
                call and the MSCDEX call.
               */
               BuildRMCS (&callStruct);
               callStruct.eax = 0x1508; // MSCDEX Absolute read
               callStruct.ebx = LOWORD(RMlpBuffer); // Offset of sect buffer
               callStruct.es = HIWORD(RMlpBuffer); // Segment of sect buffer
               callStruct.ecx = bDrive; // 0=A, 1=B, 2=C, etc.
               callStruct.edx = 1; // Read one sector
               callStruct.esi = HIWORD(dwStartSector);
               callStruct.edi = LOWORD(dwStartSector);
             
               if (fResult = SimulateRM_Int (0x2F, &callStruct))
                fResult = !(callStruct.wFlags & CARRY_FLAG);
             
               return fResult;
            }
             
            /*-------------------------------------------------------------------
              SimulateRM_Int()
             
              Allows protected-mode software to execute real-mode interrupts
              such as calls to MS-DOS, MS-DOS TSRs, MS-DOS device drivers.
             
              This function implements the "Simulate Real Mode Interrupt"
              function of the DPMI specification v0.9 and later.
             
              Parameters:
             
                bIntNum
                Number of the interrupt to simulate.
             
                lpCallStruct
                Call structure that contains params (register values)
                for bIntNum.
             
              Return Value
                SimulateRM_Int returns TRUE if it succeeded or FALSE if
                it failed.
             
              Comments
                lpCallStruct is a protected-mode selector:offset address, not
                a real-mode segment:offset address.
            -------------------------------------------------------------------*/
             
            BOOL FAR PASCAL SimulateRM_Int (BYTE bIntNum, LPRMCS lpCallStruct)
            {
               BOOL fRetVal = FALSE; // Assume failure
             
               _asm {
                push di
                mov ax, 0300h ; DPMI Simulate Real Mode Interrupt
                mov bl, bIntNum ; Number of the interrupt to simulate
                mov bh, 01h ; Bit 0 = 1; all other bits must be 0
                xor cx, cx ; No words to copy from PM to RM stack
                les di, lpCallStruct ; Real mode call structure
                int 31h ; Call DPMI
                jc END1 ; CF set if error occurred
             
                mov fRetVal, TRUE
                END1:
                pop di
                }
               return (fRetVal);
            }
             
            /*-------------------------------------------------------------------
               BuildRMCS()
             
               Initializes a real-mode call structure by zeroing all its members.
             
               Parameters:
             
                lpCallStruct
                Points to a real-mode call structure
             
               Return Value
                None.
             
               Comments
                lpCallStruct is a protected-mode selector:offset address,
                not a real-mode segment:offset address.
            -------------------------------------------------------------------*/
             
            void FAR PASCAL BuildRMCS (LPRMCS lpCallStruct)
               {
               _fmemset (lpCallStruct, 0, sizeof(RMCS));
               }
             
            REFERENCES
            ==========
             
            DOS Protected Mode Interface Specification Version 0.9.
            Programmer's Guide to Windows 95.
            Win32 SDK Online Documentation.
             
            Additional reference words: Windows 95 4.00 cdrom cd-rom absolute
            KBCategory: kbprg kbcode kbhowto
            KBSubcategory: MMCDROM
            =============================================================================

            Copyright Microsoft Corporation 1995.
0
 

Author Comment

by:frj052597
ID: 1397649
A Excellent answer but, as i wrote i have allready visited microsoft.com... So sorry it dont solve my problem!

Article ID: Q137813
Creation Date: 05-OCT-1995
Revision Date: 16-DEC-1996

I know how to make the assembler, the problem is really how to move the 2048 byte sector from the DLL to the caller.

And is it enough to call a 16bit DLL from a 32bit program?
Or must it be done in a special way (not normal DLL export)?

I need to know how it is done in Delphi!!!

0
 

Author Comment

by:frj052597
ID: 1397650
A Excellent answer but, as i wrote i have allready visited microsoft.com... So sorry it dont solve my problem!
(An why i grade you Average)

Article ID: Q137813
Creation Date: 05-OCT-1995
Revision Date: 16-DEC-1996

I know how to make the assembler, the problem is really how to move the 2048 byte sector from the DLL to the caller.

And is it enough to call a 16bit DLL from a 32bit program?
Or must it be done in a special way (not normal DLL export)?

I need to know how it is done in Delphi!!!

0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 23

Expert Comment

by:chensu
ID: 1397651
Since ReadSectorsFromCD() is exported by the DLL that is 32bit, you can call it in your 32bit applications. You can call it with a buffer allocated by you. ReadCDRomSectors called by ReadSectorsFromCD() does the work for you.

I am sorry that I cannot provide you with Delphi code because I am not familiar with Delphi.

0
 

Author Comment

by:frj052597
ID: 1397652
1) Code that resides in a Win32 DLL (the 32-bit side of the thunk).
2) Code that resides in the thunk script.
3) Code that resides in the 16-bit DLL that actually calls MSCDEX.

Where are these 3 locaded ?
1) a 32bit DLL???
2) ??? What is this?
3) a 16bit DLL???

Whay is it possible for a 32bit DLL to call a 16bit?
- Trough the trunk?

Is i not possible for a 32bit application to call a 16bit DLL trough the trunk?
0
 
LVL 23

Expert Comment

by:chensu
ID: 1397653
1. Where are these 3 located ?

Read the above article carefully please. Each section starts with the comment that states what it is.

//--------------------------------------------------------------------
// Code inside the Win32 DLL (the 32-bit side of the thunk)
// ReadSectorsFromCD() is exported by the DLL so that it can be called
// by Win32-based applications.

...

//--------------------------------------------------------------------
// Contents of the thunk script

...

//--------------------------------------------------------------------
// Code inside the 16-bit DLL. This code implements the 16-bit side of
// the thunk, and is where the calls to MSCDEX are made to read
// sectors from a compact disc.

...


2. Why is it possible for a 32bit DLL to call a 16bit?
Yes, through the thunk. For more information about thunk, please see the Win32 SDK documentations: (MSDN CD or MS Visual C++)
Win32 SDK/Programming Guides and Tools/Programmer's Guide to Windows 95/Using Windows 95 Features/Thunk Compiler.
and
Win32 SDK/Programming Guides and Tools/Programming Techniques/Generic Thunks.

0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

This article describes how to add a user-defined command button to the Windows 7 Explorer toolbar.  In the previous article (http://www.experts-exchange.com/A_2172.html), we saw how to put the Delete button back there where it belongs.  "Delete" is …
What my article will show is if you ever had to do processing to a listbox without being able to just select all the items in it. My software Visual Studio 2008 crystal report v11 My issue was I wanted to add crystal report to a form and show…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now