Index: trunk/src/kernel32/hmdisk.cpp
===================================================================
--- trunk/src/kernel32/hmdisk.cpp	(revision 8577)
+++ trunk/src/kernel32/hmdisk.cpp	(revision 8580)
@@ -1,3 +1,3 @@
-/* $Id: hmdisk.cpp,v 1.45 2002-05-17 16:49:34 sandervl Exp $ */
+/* $Id: hmdisk.cpp,v 1.46 2002-06-06 11:31:12 sandervl Exp $ */
 
 /*
@@ -20,8 +20,8 @@
 #include <win\winioctl.h>
 #include <win\ntddscsi.h>
-#include <win\wnaspi32.h>
 #include <win\aspi.h>
 #include "oslibdos.h"
 #include "osliblvm.h"
+#include "oslibcdio.h"
 #include "asmutil.h"
 
@@ -39,7 +39,5 @@
 typedef struct
 {
-    HINSTANCE hInstAspi;
-    DWORD     (WIN32API *GetASPI32SupportInfo)();
-    DWORD     (CDECL *SendASPI32Command)(LPSRB lpSRB);
+    BOOL      fCDIoSupported;    
     ULONG     driveLetter;
     ULONG     driveType;
@@ -287,17 +285,5 @@
         if(drvInfo->driveType == DRIVE_CDROM)
         {
-            drvInfo->hInstAspi = LoadLibraryA("WNASPI32.DLL");
-            if(drvInfo->hInstAspi == NULL) {
-                if(pHMHandleData->hHMHandle) OSLibDosClose(pHMHandleData->hHMHandle);
-                free(drvInfo);
-                return ERROR_INVALID_PARAMETER;
-            }
-            *(FARPROC *)&drvInfo->GetASPI32SupportInfo = GetProcAddress(drvInfo->hInstAspi, "GetASPI32SupportInfo");
-            *(FARPROC *)&drvInfo->SendASPI32Command    = GetProcAddress(drvInfo->hInstAspi, "SendASPI32Command");
-
-            if(drvInfo->GetASPI32SupportInfo() == (SS_FAILED_INIT << 8)) {
-                FreeLibrary(drvInfo->hInstAspi);
-                drvInfo->hInstAspi = 0;
-            }
+            drvInfo->fCDIoSupported = OSLibCdIoIsSupported(pHMHandleData->hHMHandle);
 
             //get cdrom signature
@@ -357,4 +343,15 @@
              return 0;
         }
+        if(drvInfo->driveType == DRIVE_CDROM)
+        {
+            drvInfo->fCDIoSupported = OSLibCdIoIsSupported(hFile);
+
+            //get cdrom signature
+            DWORD parsize = 4;
+            DWORD datasize = 4;
+            strcpy(drvInfo->signature, "CD01");
+            OSLibDosDevIOCtl(hFile, 0x80, 0x61, &drvInfo->signature[0], 4, &parsize,
+                             &drvInfo->signature[0], 4, &datasize);
+        }
         OSLibDosQueryVolumeSerialAndName(1 + drvInfo->driveLetter - 'A', &drvInfo->dwVolumelabel, NULL, 0);
         return hFile;
@@ -373,5 +370,4 @@
     if(pHMHandleData->dwUserData) {
        DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
-       if(drvInfo->hInstAspi)    FreeLibrary(drvInfo->hInstAspi);
        free(drvInfo);
     }
@@ -1426,20 +1422,18 @@
     // -------------------
 
-    case IOCTL_SCSI_PASS_THROUGH:
     case IOCTL_SCSI_MINIPORT:
     case IOCTL_SCSI_GET_INQUIRY_DATA:
+        break;
+
     case IOCTL_SCSI_GET_CAPABILITIES:
         break;
 
+    case IOCTL_SCSI_PASS_THROUGH:
+        //no break; same as IOCTL_SCSI_PASS_THROUGH_DIRECT
     case IOCTL_SCSI_PASS_THROUGH_DIRECT:
     {
         PSCSI_PASS_THROUGH_DIRECT pPacket = (PSCSI_PASS_THROUGH_DIRECT)lpOutBuffer;
-        SRB_ExecSCSICmd *psrb;
-
-        if(drvInfo->hInstAspi == NULL)
-        {
-            SetLastError(ERROR_ACCESS_DENIED);
-            return FALSE;
-        }
+        DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
+        CDIO_CMD_BUFFER cdiocmd;
 
         if(nOutBufferSize < sizeof(SCSI_PASS_THROUGH_DIRECT) ||
@@ -1449,62 +1443,55 @@
             return FALSE;
         }
+        
+        if(!drvInfo || drvInfo->fCDIoSupported == FALSE) {
+            dprintf(("os2cdrom.dmd CD interface not supported!!"));
+            SetLastError(ERROR_ACCESS_DENIED);
+            return FALSE;
+        }
         if(lpBytesReturned) {
             *lpBytesReturned = 0;
         }
 
-        psrb = (SRB_ExecSCSICmd *)alloca(sizeof(SRB_ExecSCSICmd)+pPacket->SenseInfoLength);
-        if(psrb == NULL) {
-            dprintf(("not enough memory!!"));
-            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-            return FALSE;
-        }
-        memset(psrb, 0, sizeof(*psrb));
-        psrb->SRB_Cmd        = SC_EXEC_SCSI_CMD;
-        psrb->SRB_Status     = pPacket->ScsiStatus;
-        psrb->SRB_HaId       = pPacket->PathId;
-        psrb->SRB_Target     = pPacket->TargetId;
-        psrb->SRB_Lun        = pPacket->Lun;
-        psrb->SRB_BufLen     = pPacket->DataTransferLength;
-        psrb->SRB_SenseLen   = pPacket->SenseInfoLength;
-        psrb->SRB_CDBLen     = pPacket->CdbLength;
+        if(pPacket->CdbLength > sizeof(cdiocmd.arCDB)) {
+            dprintf(("CDB buffer too big (%d)!!", pPacket->CdbLength));
+            SetLastError(ERROR_INVALID_PARAMETER);
+            return FALSE;
+        }
+
+        memset(&cdiocmd, 0, sizeof(cdiocmd));
+
         switch(pPacket->DataIn) {
         case SCSI_IOCTL_DATA_OUT:
-             psrb->SRB_Flags = 0x2 << 3;
-             break;
+            cdiocmd.flDirection = CMDDIR_OUTPUT;
+            break;
         case SCSI_IOCTL_DATA_IN:
-             psrb->SRB_Flags = 0x1 << 3;
-             break;
+            cdiocmd.flDirection = CMDDIR_INPUT;
+            break;
         case SCSI_IOCTL_DATA_UNSPECIFIED:
-             psrb->SRB_Flags = 0x3 << 3;
-             break;
-        }
-        if(pPacket->CdbLength > 16) {
-             SetLastError(ERROR_INVALID_PARAMETER);
-             return FALSE;
-        }
+            cdiocmd.flDirection = CMDDIR_OUTPUT|CMDDIR_INPUT;;
+            break;
+        }
+
+        cdiocmd.cbCDB = pPacket->CdbLength;
+        memcpy(cdiocmd.arCDB, pPacket->Cdb, pPacket->CdbLength);
+
         dprintf(("IOCTL_SCSI_PASS_THROUGH_DIRECT %x len %x, %x%02x%02x%02x %x%02x", pPacket->Cdb[0], pPacket->DataTransferLength, pPacket->Cdb[2], pPacket->Cdb[3], pPacket->Cdb[4], pPacket->Cdb[5], pPacket->Cdb[7], pPacket->Cdb[8]));
-        psrb->SRB_BufPointer = (BYTE *)pPacket->DataBuffer;
-        memcpy(&psrb->CDBByte[0], &pPacket->Cdb[0], 16);
-        if(psrb->SRB_SenseLen) {
-            memcpy(&psrb->SenseArea[0], (char *)pPacket + pPacket->SenseInfoOffset, psrb->SRB_SenseLen);
-        }
-        //TODO: pPacket->TimeOutValue ignored
-        int rc = drvInfo->SendASPI32Command((LPSRB)psrb);
-        if(rc != SS_COMP) {
-            dprintf(("SendASPI32Command failed with error %d", rc));
-            if(rc == SS_ERR) {
-                 SetLastError(ERROR_ADAP_HDW_ERR); //returned by NT4, SP6
+
+        if(OSLibCdIoSendCommand(pHMHandleData->hHMHandle, &cdiocmd, pPacket->DataBuffer, pPacket->DataTransferLength) == FALSE) {
+            dprintf(("OSLibCdIoSendCommand failed!!"));
+            pPacket->ScsiStatus = SS_ERR;
+            SetLastError(ERROR_ADAP_HDW_ERR); //returned by NT4, SP6
+            return FALSE;
+        }
+
+        if(pPacket->SenseInfoLength) {
+            if(OSLibCdIoRequestSense(pHMHandleData->hHMHandle, (char *)pPacket + pPacket->SenseInfoOffset, pPacket->SenseInfoLength) == FALSE) {
+                dprintf(("OSLibCdIoRequestSense failed!!"));
+                pPacket->ScsiStatus = SS_ERR;
+                SetLastError(ERROR_ADAP_HDW_ERR); //returned by NT4, SP6
+                return FALSE;
             }
-            else SetLastError(ERROR_GEN_FAILURE);
-            return FALSE;
-        }
-        pPacket->ScsiStatus = rc;
-        if(lpBytesReturned) {
-            *lpBytesReturned = 0;
-        }
-        pPacket->DataTransferLength = psrb->SRB_BufLen;
-        if(psrb->SRB_SenseLen) {
-            memcpy((char *)pPacket + pPacket->SenseInfoOffset, &psrb->SenseArea[0], psrb->SRB_SenseLen);
-        }
+        }
+        pPacket->ScsiStatus = SS_COMP;
         SetLastError(ERROR_SUCCESS);
         return TRUE;
@@ -1512,7 +1499,11 @@
     case IOCTL_SCSI_GET_ADDRESS:
     {
-        DWORD numAdapters, rc;
-        SRB   srb;
-        int   i, j, k;
+        DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
+
+        if(!drvInfo || drvInfo->fCDIoSupported == FALSE) {
+            dprintf(("os2cdrom.dmd CD interface not supported!!"));
+            SetLastError(ERROR_ACCESS_DENIED);
+            return FALSE;
+        }
 
         if(!lpOutBuffer || nOutBufferSize < 8) {
@@ -1524,51 +1515,9 @@
         addr->PortNumber = 0;
         addr->PathId     = 0;
-
-        if(drvInfo->hInstAspi == NULL) {
-            SetLastError(ERROR_ACCESS_DENIED);
-            return FALSE;
-        }
-
-        numAdapters = drvInfo->GetASPI32SupportInfo();
-
-        memset(&srb, 0, sizeof(srb));
-        srb.common.SRB_Cmd = SC_HA_INQUIRY;
-        rc = drvInfo->SendASPI32Command(&srb);
-
-        char drivename[3];
-        drivename[0] = (char)drvInfo->driveLetter;
-        drivename[1] = ':';
-        drivename[2] = 0;
-
-        for(i=0;i<LOBYTE(numAdapters);i++) {
-            for(j=0;j<8;j++) {
-                for(k=0;k<16;k++) {
-                    memset(&srb, 0, sizeof(srb));
-                    srb.common.SRB_Cmd     = SC_GET_DEV_TYPE;
-                    srb.devtype.SRB_HaId   = i;
-                    srb.devtype.SRB_Target = j;
-                    srb.devtype.SRB_Lun    = k;
-                    rc = drvInfo->SendASPI32Command(&srb);
-                    if(rc == SS_COMP) {
-                        if(srb.devtype.SRB_DeviceType == SS_DEVTYPE_CDROM &&
-                           GetDriveTypeA(drivename) == DRIVE_CDROM)
-                        {
-                            goto done;
-                        }
-                    }
-                }
-            }
-        }
-done:
-        if(rc == SS_COMP) {
-            addr->TargetId   = j;
-            addr->Lun        = k;
-            SetLastError(ERROR_SUCCESS);
-        }
-        else    SetLastError(ERROR_FILE_NOT_FOUND); //todo
+        //irrelevant, since os2cdrom.dmd doesn't need them
+        addr->TargetId   = 1;
+        addr->Lun        = 0;
+        SetLastError(ERROR_SUCCESS);
         return TRUE;
-failure:
-        SetLastError(ERROR_INVALID_PARAMETER); //todo
-        return FALSE;
     }
 
Index: trunk/src/kernel32/kernel32.mak
===================================================================
--- trunk/src/kernel32/kernel32.mak	(revision 8577)
+++ trunk/src/kernel32/kernel32.mak	(revision 8580)
@@ -1,3 +1,3 @@
-# $Id: kernel32.mak,v 1.30 2002-05-10 14:55:12 sandervl Exp $
+# $Id: kernel32.mak,v 1.31 2002-06-06 11:31:12 sandervl Exp $
 
 #
@@ -139,4 +139,5 @@
 $(OBJDIR)\hmnpipe.obj \
 $(OBJDIR)\hmdisk.obj \
+$(OBJDIR)\oslibcdio.obj \
 $(OBJDIR)\version.obj \
 !ifdef DEBUG
Index: trunk/src/kernel32/oslibcdio.cpp
===================================================================
--- trunk/src/kernel32/oslibcdio.cpp	(revision 8580)
+++ trunk/src/kernel32/oslibcdio.cpp	(revision 8580)
@@ -0,0 +1,360 @@
+/*
+ * OS2CDROM.DMD interface for sending SCSI commands
+ *
+ * Based on example code by:
+ *	(c) 2001 S&T Systemtechnik GmbH					                    
+ *									                                    
+ *	erzeugt:	15.02.01	R.Ihle				                        
+ *
+ * Project Odin Software License can be found in LICENSE.TXT
+ *
+ */
+
+#define	INCL_NOPMAPI
+#define	INCL_DOSDEVICES
+#define	INCL_DOSDEVIOCTL
+#define	INCL_DOSFILEMGR
+#define	INCL_DOSMISC
+#include <os2wrap.h>
+
+#include "cdioctl.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+
+#include "oslibCdIo.h"
+#include <win32type.h>
+
+
+//needed for high memory support check
+DWORD OSLibDosDevIOCtl( DWORD hFile, DWORD dwCat, DWORD dwFunc,
+                        PVOID pParm, DWORD dwParmMaxLen, DWORD *pdwParmLen,
+                        PVOID pData, DWORD dwDataMaxLen, DWORD *pdwDataLen);
+
+
+//----------------------------------------------------------------------//
+//	Initialize CD/DVD drive access					//
+//----------------------------------------------------------------------//
+
+BOOL OSLibCdIoInitialize(void)
+{
+    ULONG ulAction, ulFeatures;
+    int	  fResult = 0;
+    HFILE hDev;
+
+    if( DosOpen("CD-ROM2$", &hDev, &ulAction, 0, FILE_NORMAL,
+	            OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
+	            OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE |
+	            OPEN_FLAGS_FAIL_ON_ERROR, NULL) == 0 )
+    {
+        fResult = DosDevIOCtl(hDev, IOCTL_CDROMDISK2, CDROMDISK2_FEATURES,
+			                  NULL, 0, NULL, &ulFeatures, sizeof(ulFeatures), NULL) == 0 &&
+	              (ulFeatures & FEATURE_EXECMD_SUPPORT);
+
+        DosClose(hDev);
+    }
+
+    return fResult;
+}
+
+
+//----------------------------------------------------------------------//
+//	Unload ASPI manager						//
+//----------------------------------------------------------------------//
+
+BOOL OSLibCdIoTerminate(void)
+{
+    return 1;
+}
+
+
+//----------------------------------------------------------------------//
+//	Open drive							//
+//----------------------------------------------------------------------//
+
+BOOL OSLibCdIoIsSupported(HFILE hDisk)
+{
+    ULONG ulAction, ulCDSig;
+
+    ulCDSig = ('C') | ('D' << 8) | ('9' << 16) | ('9' << 24);
+
+    if(OSLibCdIoInitialize() == FALSE) {
+        return FALSE;
+    }
+
+    if(DosDevIOCtl(hDisk, IOCTL_CDROMDISK, CDROMDISK_GETDRIVER, &ulCDSig, sizeof(ulCDSig), NULL,
+		           &ulCDSig, sizeof(ulCDSig), NULL) == 0 &&
+	    ulCDSig == (('C') | ('D' << 8) | ('0' << 16) | ('1' << 24)) )
+    {
+        return TRUE;
+    }
+    return FALSE;
+}
+
+
+//----------------------------------------------------------------------//
+//	Send command to drive						//
+//----------------------------------------------------------------------//
+
+BOOL OSLibCdIoSendCommand(HCDIO hCdIo, CDIO_CMD_BUFFER *pCmdBuf, void *pData, unsigned cbData)
+{
+    struct ExecCmd	Param;
+    ULONG			ulDummy, ParmLen, DataLen;
+
+    if( !pData || !cbData )
+    {
+        ulDummy = 0;  pData = &ulDummy;  cbData = sizeof(ulDummy);
+    }
+
+    Param.ID_code     = 'C' | ('D'<<8) | ('0'<<16) | ('1'<<24);
+    Param.data_length = (USHORT)cbData;
+    Param.cmd_length  = pCmdBuf->cbCDB;
+    Param.flags       = (USHORT)
+		      (( pCmdBuf->flDirection & 1 ) ? EX_DIRECTION_IN : 0);
+    memcpy(Param.cmd_buffer, pCmdBuf->arCDB, sizeof(Param.cmd_buffer));
+
+
+    ParmLen = sizeof(Param);
+    DataLen = cbData;
+    return OSLibDosDevIOCtl((HFILE)hCdIo, IOCTL_CDROMDISK, CDROMDISK_EXECMD,
+		                     &Param, ParmLen, &ParmLen, pData, cbData, &DataLen) == 0;
+}
+
+
+//----------------------------------------------------------------------//
+//	Load / Eject disk						//
+//----------------------------------------------------------------------//
+
+BOOL OSLibCdIoLoadEjectDisk(HCDIO hCdIo, int fLoad)
+{
+    CDIO_CMD_BUFFER	CmdBuf;
+
+    memset(&CmdBuf, 0, sizeof(CmdBuf));
+    CmdBuf.flDirection = CMDDIR_OUTPUT;
+    CmdBuf.cbCDB       = 6;
+    CmdBuf.arCDB[0]    = 0x1b;		// START STOP UNIT command
+    CmdBuf.arCDB[4]    = (unsigned char)(( fLoad ) ?  0x03 : 0x02);
+					    // Bit 1: 0:Start/Stop, 1:Load/Eject
+					    // Bit 0: 0:Stop/Eject, 1:Start/Load
+    return OSLibCdIoSendCommand(hCdIo, &CmdBuf, NULL, 0);
+}
+
+
+//----------------------------------------------------------------------//
+//	Test drive readyness						//
+//----------------------------------------------------------------------//
+
+BOOL OSLibCdIoUnitReady(HCDIO hCdIo)
+{
+    CDIO_CMD_BUFFER	CmdBuf;
+
+    memset(&CmdBuf, 0, sizeof(CmdBuf));
+    CmdBuf.flDirection = CMDDIR_OUTPUT;
+    CmdBuf.cbCDB       = 6;
+//  CmdBuf.arCDB[0]    = 0x00;		// TEST UNIT READY command
+
+    return OSLibCdIoSendCommand(hCdIo, &CmdBuf, NULL, 0);
+}
+
+
+//----------------------------------------------------------------------//
+//	Reset drive							//
+//----------------------------------------------------------------------//
+
+BOOL OSLibCdIoResetUnit(HCDIO hCdIo)
+{
+    CDIO_CMD_BUFFER	CmdBuf;
+
+    memset(&CmdBuf, 0, sizeof(CmdBuf));
+    CmdBuf.flDirection = CMDDIR_OUTPUT;
+    CmdBuf.cbCDB       = 6;
+    CmdBuf.arCDB[0]    = 0x01;		// REZERO command
+
+    return OSLibCdIoSendCommand(hCdIo, &CmdBuf, NULL, 0);
+}
+
+
+//----------------------------------------------------------------------//
+//	Query information about drive					//
+//----------------------------------------------------------------------//
+
+BOOL OSLibCdIoInquiry(HCDIO hCdIo, unsigned uPageCode, void *pData, unsigned cbData)
+{
+    CDIO_CMD_BUFFER	CmdBuf;
+
+    if( cbData > 255 )	cbData = 255;
+
+    memset(&CmdBuf, 0, sizeof(CmdBuf));
+    CmdBuf.flDirection = CMDDIR_INPUT;
+    CmdBuf.cbCDB       = 6;
+    CmdBuf.arCDB[0]    = 0x12;		// INQUIRY CAPACITY command
+    CmdBuf.arCDB[4]    = (unsigned char)cbData;
+
+    if( uPageCode )
+    {
+        CmdBuf.arCDB[1]  = 1;		// enable vital product data
+        CmdBuf.arCDB[2]  = (unsigned char)uPageCode;
+    }
+
+    return OSLibCdIoSendCommand(hCdIo, &CmdBuf, pData, cbData);
+}
+
+
+//----------------------------------------------------------------------//
+//	Query sense information						//
+//----------------------------------------------------------------------//
+
+BOOL OSLibCdIoRequestSense(HCDIO hCdIo, void *pData, unsigned cbData)
+{
+    CDIO_CMD_BUFFER	CmdBuf;
+
+    if( cbData > 255 )	cbData = 255;
+
+    memset(&CmdBuf, 0, sizeof(CmdBuf));
+    CmdBuf.flDirection = CMDDIR_INPUT;
+    CmdBuf.cbCDB       = 6;
+    CmdBuf.arCDB[0]    = 0x03;		// REQUEST SENSE command
+    CmdBuf.arCDB[4]    = (unsigned char)cbData;
+
+    return OSLibCdIoSendCommand(hCdIo, &CmdBuf, pData, cbData);
+}
+
+
+//----------------------------------------------------------------------//
+//	Query disc capacity						//
+//----------------------------------------------------------------------//
+
+BOOL OSLibCdIoQueryCapacity(HCDIO hCdIo, unsigned *pctBlocks, unsigned *pcbBlock)
+{
+    CDIO_CMD_BUFFER	CmdBuf;
+    unsigned		arResult[2];
+
+    memset(&CmdBuf, 0, sizeof(CmdBuf));
+    CmdBuf.flDirection = CMDDIR_INPUT;
+    CmdBuf.cbCDB       = 10;
+    CmdBuf.arCDB[0]    = 0x25;		// READ CAPACITY command
+
+    if( OSLibCdIoSendCommand(hCdIo, &CmdBuf, arResult, sizeof(arResult)) )
+    {
+        *pctBlocks = (arResult[0] << 24) |
+		    ((arResult[0] & 0x0000ff00) << 8) |
+		    ((arResult[0] & 0x00ff0000) >> 8) |
+		    (arResult[0] >> 24);
+    
+        *pcbBlock =  (arResult[1] << 24) |
+		    ((arResult[1] & 0x0000ff00) << 8) |
+		    ((arResult[1] & 0x00ff0000) >> 8) |
+		    (arResult[1] >> 24);
+
+        return 1;
+    }
+
+    return 0;
+}
+
+
+//----------------------------------------------------------------------//
+//	Read data							//
+//----------------------------------------------------------------------//
+
+BOOL OSLibCdIoReadBlock(HCDIO hCdIo, unsigned uLBA, void *pData, unsigned cbData)
+{
+    CDIO_CMD_BUFFER	CmdBuf;
+
+    memset(&CmdBuf, 0, sizeof(CmdBuf));
+    CmdBuf.flDirection = CMDDIR_INPUT;
+    CmdBuf.cbCDB       = 10;
+//  CmdBuf.arCDB[0]    = 0x3e;		// READ LONG command MODE SELECT ???
+//  CmdBuf.arCDB[1]    = 0x02;		// Bit 1: perform ECC
+
+    CmdBuf.arCDB[0]    = 0x28;		// READ command
+    CmdBuf.arCDB[2]    = (unsigned char)(uLBA >> 24);
+    CmdBuf.arCDB[3]    = (unsigned char)(uLBA >> 16);
+    CmdBuf.arCDB[4]    = (unsigned char)(uLBA >> 8);
+    CmdBuf.arCDB[5]    = (unsigned char)(uLBA);
+    CmdBuf.arCDB[7]    = 0;
+    CmdBuf.arCDB[8]    = 1;
+
+    return ( cbData > 2047 ) ? OSLibCdIoSendCommand(hCdIo, &CmdBuf, pData, cbData) : 0;
+}
+
+
+//----------------------------------------------------------------------//
+//	Query bit mask of all CD drives					//
+//----------------------------------------------------------------------//
+
+ULONG OSLibCdIoQueryDriveList(void)
+{
+    BIOSPARAMETERBLOCK    BPB;
+    HFILE			hDev;
+    struct DrvInfo	CDInfo;
+    ULONG			ulAction, ulParam, uDriveMap = 0;
+
+    if( DosOpen("CD-ROM2$", &hDev, &ulAction, 0, FILE_NORMAL,
+	        OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
+	        OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE |
+	        OPEN_FLAGS_FAIL_ON_ERROR, NULL) == 0 )
+    {
+        if( DosDevIOCtl(hDev, IOCTL_CDROMDISK2, CDROMDISK2_DRVINFO,
+		        NULL, 0, NULL, &CDInfo, sizeof(CDInfo), NULL) == 0 )
+        {
+        // Workaround for Warp4/FP14 kernel bug ...
+        ulParam = CDInfo.usFirstDrvNo << 8;
+        while( CDInfo.usFirstDrvNo <= ('Z' - 'A') &&
+	        DosDevIOCtl((HFILE)-1, IOCTL_DISK, DSK_GETDEVICEPARAMS,
+			            &ulParam, 2, NULL, &BPB, sizeof(BPB), NULL) == 0 &&
+			            BPB.bDeviceType != DEVTYPE_UNKNOWN )
+        {
+	            ulParam = ++CDInfo.usFirstDrvNo;
+        }
+
+        if( CDInfo.usFirstDrvNo > ('Z' - 'A') )	CDInfo.usDrvCount = 0;
+
+        while( CDInfo.usDrvCount-- )
+	            uDriveMap |= 1 << (CDInfo.usFirstDrvNo + CDInfo.usDrvCount);
+        }
+
+        DosClose(hDev);
+    }
+    
+    return uDriveMap;
+}
+
+
+//----------------------------------------------------------------------//
+//	Query fully qualified path name of a given file			//
+//----------------------------------------------------------------------//
+
+BOOL OSLibCdIoQueryFullName(char *pchPartName, char *pchFullName, unsigned cbFullName)
+{
+    APIRET	rc;
+
+    DosError(FERR_DISABLEHARDERR);
+    rc = DosQueryPathInfo(pchPartName, FIL_QUERYFULLNAME, pchFullName, cbFullName);
+    DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
+
+    return rc == 0;
+}
+
+
+//----------------------------------------------------------------------//
+//	Read volume label		 				//
+//----------------------------------------------------------------------//
+BOOL OSLibCdIoQueryVolumeLabel(char chDrive, char *pchLabel, unsigned cbLabel)
+{
+    FSINFO	FsInfo;
+
+    memset(pchLabel, '\0', cbLabel);
+    if( cbLabel && DosQueryFSInfo((chDrive & 0x5f) - 'A' + 1,
+				    FSIL_VOLSER, &FsInfo, sizeof(FsInfo)) == 0 )
+    {
+        strncpy(pchLabel, FsInfo.vol.szVolLabel, cbLabel);
+        pchLabel[cbLabel-1] = '\0';
+        return 1;
+    }
+
+    return 0;
+}
+
+
Index: trunk/src/kernel32/oslibcdio.h
===================================================================
--- trunk/src/kernel32/oslibcdio.h	(revision 8580)
+++ trunk/src/kernel32/oslibcdio.h	(revision 8580)
@@ -0,0 +1,56 @@
+/*
+ * OS2CDROM.DMD interface for sending SCSI commands
+ *
+ * Based on example code by:
+ *	(c) 2001 S&T Systemtechnik GmbH					                    
+ *									                                    
+ *	erzeugt:	15.02.01	R.Ihle				                        
+ *
+ * Project Odin Software License can be found in LICENSE.TXT
+ *
+ */
+
+#ifndef	__CDIO_H
+#define	__CDIO_H
+
+#ifdef	__cplusplus
+  extern "C" {
+#endif
+
+typedef ULONG HCDIO;
+
+typedef struct
+{
+  unsigned	flDirection;		// direction flag
+  unsigned	cbCDB;			    // command length
+  unsigned char	arCDB[16];		// actual CdIo command
+} CDIO_CMD_BUFFER;
+
+#define	CMDDIR_OUTPUT		0
+#define	CMDDIR_INPUT		1
+
+BOOL    OSLibCdIoInitialize(void);
+BOOL    OSLibCdIoTerminate(void);
+
+BOOL    OSLibCdIoIsSupported(HFILE hDisk);
+BOOL 	OSLibCdIoSendCommand(HCDIO hCdIo, CDIO_CMD_BUFFER *pCmd, void *pData, unsigned cbData);
+
+BOOL    OSLibCdIoLoadEjectDisk(HCDIO hCdIo, int fLoad);
+BOOL    OSLibCdIoResetUnit(HCDIO hCdIo);
+BOOL    OSLibCdIoUnitReady(HCDIO hCdIo);
+BOOL    OSLibCdIoInquiry(HCDIO hCdIo, unsigned uPageCode, void *pData, unsigned cbData);
+BOOL    OSLibCdIoRequestSense(HCDIO hCdIo, void *pData, unsigned cbData);
+BOOL    OSLibCdIoQueryCapacity(HCDIO hCdIo, unsigned *pctBlocks, unsigned *pcbBlock);
+BOOL    OSLibCdIoReadBlock(HCDIO hCdIo, unsigned uLBA, void *pData, unsigned cbData);
+
+ULONG   OSLibCdIoQueryDriveList(void);
+BOOL	OSLibCdIoQueryFullName(char *pchPartName, char *pchFullName, unsigned cbFullName);
+BOOL	OSLibCdIoQueryVolumeLabel(char chDrive, char *pchLabel, unsigned cbLabel);
+
+#ifdef	__cplusplus
+  }
+#endif
+
+#endif
+
+
