{+------------------------------------------------------------ | Unit PBCDInt | | Version: 1.0 Last modified: 02/27/95, 22:09:07 | Author : P. Below CIS [100113,1101] | Project: Common utilities | Description: | This DLL exports a number of functions of the MSCDEX interface | for the use of other Windows programs. Was originally written | for a Visual Basic app that needed a method do detect whether | a given drive is a CD-ROM and whether it contains a CD or not. | | Released to public domain +------------------------------------------------------------} Library PBCDINT; Uses WinTypes, WinProcs, Utils; Const CD_ERROR = -1; CD_NOTACDDRIVE = 0; CD_DRIVEEMPTY = 1; CD_CDFOUND = 2; (* returns TRUE if MSCDEX is loaded, False otherwise *) FUNCTION Is_MSCDEX_loaded: BOOLEAN; assembler; ASM mov AX, $1500 (* MSCDEX installed check *) xor BX, BX int $2F xor ax, ax (* set default return value to false *) or BX, BX (* returns bx <> 0 if MSCDEX installed *) jz @no_mscdex mov al, TRUE @no_mscdex: END; (* returns -1 ( VB True ) if drive is CD-ROM, 0 otherwise. drivenum = 1 for A:, 2 for B: etc. *) Function CDDriveIsCD( drivenum: Integer): Integer; export; Begin ASM mov AX, $150B (* MSCDEX check drive function *) mov CX, drivenum sub BX,BX int $2F cmp bx, $ADAD jne @no_cdrom or AX, AX jz @no_cdrom mov @result, $FFFF jmp @exit @no_cdrom: mov @result, 0 @exit: END; End; (* returns one of the CD_xxx constants. drivenum = 1 for A:, 2 for B: etc. *) Function CDDriveStatus( drivenum: integer ): integer; export; Var RealModeReg: TRealModeReg; dwGlobalDosBuffer: LongInt; Begin If CDDriveIsCD( drivenum ) = 0 Then CDDriveStatus := CD_NOTACDDRIVE Else Begin CDDriveStatus := CD_ERROR; { alloc a buffer for the MSCDEX call to put the copyright filename into. this has to reside in low dos memory since the function needs a real mode pointer in es:bx. We ignore the info put into the buffer. } dwGlobalDosBuffer := GlobalDosAlloc(40); if (dwGlobalDosBuffer <> 0) then Begin { initialize the real mode register structure } FillChar(RealModeReg, sizeof(RealModeReg), 0); RealModeReg.rmEAX := $1502; RealModeReg.rmECX := Longint(drivenum); RealModeReg.rmES := HIWORD(dwGlobalDosBuffer); { real mode segment } RealModeReg.rmEBX := 0; { offset is zero } { simulate the real mode interrupt. we have to jump thru these hoops because loading a real mode segment value into a register in protected mode is a sure recipe for a GPF. } if RealInt($2F, RealModeReg) then If (LoWord(RealModeReg.rmCPUFlags) and 1) = 0 Then { carry clear, CD drive containing a readable CD } CDDriveStatus := CD_CDFOUND Else If LoWord( RealModeReg.rmEAX ) = $F Then { DOS error "invalid drive" } CDDriveStatus := CD_NOTACDDRIVE Else { normally DOS error 1Eh: read fault } CDDriveStatus := CD_DRIVEEMPTY; GlobalDosFree(LOWORD(dwGlobalDosBuffer)); End; End; End; (* returns the number of CD drives supported by MSCDEX *) Function CDNumberOfDrives: Integer; export; Begin ASM mov AX, $1500 (* MSCDEX installed check *) xor BX, BX int $2F mov @result, bx END; End; (* returns the number of the first drive supported by MSCDEX *) Function CDFirstDrive: Integer; export; Begin ASM mov AX, $1500 (* MSCDEX installed check *) xor BX, BX int $2F mov @result, cx END; End; exports CDDriveStatus index 1, CDNumberOfDrives index 2, CDFirstDrive index 3, CDDriveIsCD index 4; Begin (* make the fixed DLL data segment moveable *) GlobalPageUnlock( DSeg ); GlobalReAlloc(DSeg, 0, GMEM_MODIFY or GMEM_MOVEABLE); End.