Comment les Applications Win32 peuvent lire les secteurs de CD-ROM dans Windows 95

Traductions disponibles Traductions disponibles
Numéro d'article: 137813 - Voir les produits auxquels s'applique cet article
Cet article a été archivé. Il est proposé « en l'état » et ne sera plus mis à jour.
Agrandir tout | Réduire tout

Résumé

Certaines applications Win32, telles que les applications multimédias et jeux, est nécessaire de lire les secteurs directement à partir des CD-ROM d'implémenter des accès personnalisés ou de lire la mise en cache pour optimiser l'accès au lecteur de CD-ROM à des fins spécifiques. Cet article fournit des informations et exemple de code qui montre comment les applications Win32 peuvent lire les secteurs à partir des CD-ROM sous Windows 95.

Plus d'informations

Le CDFS (Compact Disc File System) Windows 95 est un pilote de CD-ROM en mode protégé qui implémente les fonctions de 2Fh interruption de MSCDEX en mode V86 comme interface unique pouvant être appelé par l'application. Cette interface permet de remplacer les pilotes de CD ROM et Mscdex.exe en mode réel et toujours être totalement compatible avec les applications existantes pour MS-DOS et Windows 3.x. En fait, les applications pour MS-DOS et Windows 3.x ne sera pas en mesure de faire la différence entre CDFS et Mscdex.exe.

Windows 95 fournit une interface pour les applications Win32 lire des secteurs de disques compacts. Cette interface diffère considérablement de celle fournie par Windows NT. Tandis que les applications Win32 sur Windows NT utilisent CreateFile() et ReadFile() pour lire les secteurs à partir des CD-ROM, applications Win32 qui s'exécutent sur Windows 95 doivent utiliser une méthode indirecte qui implique le médiateur à une DLL 16 bits qui appelle MSCDEX Int 2Fh fonctions.

Car l'interface MSCDEX peut être appelé uniquement en mode V86, Win32 applications doivent thunk pour une DLL 16 bits et la DLL 16 bits doit utiliser la fonction d'interface de mode protégé DOS (DPMI) simuler Real Mode interruption pour appeler ses fonctions. L'application Win32 doit passer une mémoire tampon à la DLL 16 bits. À l'intérieur de thunk, la DLL 16 bits Obtient les données de secteur de MSCDEX, copie en mémoire tampon de l'application Win32 et retourne à l'application Win32.



Le code suivant montre comment lire des secteurs à partir d'un CD-ROM à l'aide de la méthode décrite ci-dessus. Étant donné que le code implémente un thunk plat, elle est divisée en trois sections :
  • Code qui réside dans une DLL Win32 (le côté 32 bits du thunk).
  • Code qui réside dans le script de thunk.
  • Code qui réside dans la DLL 16 bits qui appelle en réalité 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
        accommodate 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 number 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
        accommodate 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 accommodate 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));
   }
				

Références

DOS Protected Mode Interface Specification Version 0,9.
Guide du programmeur pour Windows 95.
Documentation en ligne du Kit de développement logiciel (SDK) Win32.

Propriétés

Numéro d'article: 137813 - Dernière mise à jour: samedi 22 février 2014 - Version: 3.2
Les informations contenues dans cet article s'appliquent au(x) produit(s) suivant(s):
  • Microsoft Win32 Application Programming Interface sur le système suivant
    • Microsoft Windows 95
    • Microsoft Windows 98 Standard Edition
    • Microsoft Windows Millennium Edition
    • Microsoft Windows NT 4.0
Mots-clés : 
kbnosurvey kbarchive kbmt kbapi kbcode kbkernbase KB137813 KbMtfr
Traduction automatique
IMPORTANT : Cet article est issu du système de traduction automatique mis au point par Microsoft (http://support.microsoft.com/gp/mtdetails). Un certain nombre d?articles obtenus par traduction automatique sont en effet mis à votre disposition en complément des articles traduits en langue française par des traducteurs professionnels. Cela vous permet d?avoir accès, dans votre propre langue, à l?ensemble des articles de la base de connaissances rédigés originellement en langue anglaise. Les articles traduits automatiquement ne sont pas toujours parfaits et peuvent comporter des erreurs de vocabulaire, de syntaxe ou de grammaire (probablement semblables aux erreurs que ferait une personne étrangère s?exprimant dans votre langue !). Néanmoins, mis à part ces imperfections, ces articles devraient suffire à vous orienter et à vous aider à résoudre votre problème. Microsoft s?efforce aussi continuellement de faire évoluer son système de traduction automatique.
La version anglaise de cet article est la suivante: 137813
L'INFORMATION CONTENUE DANS CE DOCUMENT EST FOURNIE PAR MICROSOFT SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE. L'UTILISATEUR ASSUME LE RISQUE DE L'UTILISATION DU CONTENU DE CE DOCUMENT. CE DOCUMENT NE PEUT ETRE REVENDU OU CEDE EN ECHANGE D'UN QUELCONQUE PROFIT.

Envoyer des commentaires

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com