⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dvdioctl.cpp

📁 EP931X系列的WinCE显卡驱动源代码
💻 CPP
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
#include <atamain.h>


static DWORD rkret[] =
{
    sizeof (RKFMT_AGID) << 24,
    sizeof (RKFMT_CHLGKEY) << 24,
    sizeof (RKFMT_BUS) << 24,
    sizeof (RKFMT_BUS) << 24,
    sizeof (RKFMT_TITLE) << 24,
    0,
    0,
    0,
    sizeof (RKFMT_RPC) << 24,
};


DWORD EndSwap(DWORD dwInput)
{
    register DWORD dwResult;
    
    dwResult = (dwInput << 24) | ((dwInput & 0xff00) << 8) | ((dwInput & 0xff0000) >> 8) | (dwInput >> 24);
        return(dwResult);
}


/*
** setup_readkey()
**
**    setup a read key command
**
** Arguments:
**
** Returns:
**
** Side Effects:  none
*/
DWORD DVDSetupReadTitleKey(ATAPI_COMMAND_PACKET *pCmdPkt, BYTE bKeyType, BYTE bAgid, DWORD dwLBA)
{
    DWORD dwRet;
    PRKCDB pcdb = (PRKCDB)(pCmdPkt);

    pcdb->OpCode = DVDOP_REPORT_KEY;
    pcdb->KeyFmt = (bAgid << 6) | bKeyType;
    pcdb->Lun = 0;

    if (bKeyType > (sizeof(rkret) / sizeof (DWORD)))
    {
        dwRet = 0;
    }
    else
    {
        dwRet = rkret[bKeyType];
    }


    //
    // set up endian swapped allocation length, and clear reserved
    //

    *(PDWORD)(&pcdb->Reserved) = dwRet;

    //
    // set up the LBA field
    //
    
    pcdb->LBA = EndSwap(dwLBA);

    pcdb->NACA = 0;

    return(EndSwap(dwRet));
}

DWORD DVDSetupReadDiscKey( ATAPI_COMMAND_PACKET *pCmdPkt, BYTE bAgid)
{
    PRDVDCDB pcdb = (PRDVDCDB)(pCmdPkt);

    pcdb->OpCode = DVDOP_READ_DVD_STRUC;

    pcdb->Lun = 0;
    *((DWORD *)&pcdb->RMDLBA) = 0;
    pcdb->Layer = 0;
    pcdb->Format = DVDSTRUC_FMT_DISCKEY;
    pcdb->Len = (USHORT)(sizeof (RKFMT_DISC) << 8 | sizeof (RKFMT_DISC) >>8);
    pcdb->agid = bAgid;
    pcdb->NACA = 0;

    return(sizeof (RKFMT_DISC));
}

DWORD DVDSetupReadKey(ATAPI_COMMAND_PACKET *pCmdPkt, PDVD_COPY_PROTECT_KEY pKey)
{
    switch (pKey->KeyType)
    {
    case DvdTitleKey:
        return(DVDSetupReadTitleKey(pCmdPkt, (BYTE)(pKey->KeyType), (BYTE)pKey->SessionId, pKey->StartAddr +1));
    case DvdDriveKey:
        return(DVDSetupReadDiscKey(pCmdPkt, (BYTE)((pKey->SessionId) << 6)));
    default:
        return(DVDSetupReadTitleKey(pCmdPkt, (BYTE)(pKey->KeyType), (BYTE)pKey->SessionId, 0));
    }
    return 0;
}

DWORD CopyDVDKey(DWORD dwKeyLength,PDVD_COPY_PROTECT_KEY pKey ,PRKFMT_TITLE pTitle  )
{
    DWORD dwTmp;
    PBYTE psrc, pdest;

    dwTmp = dwKeyLength - 4;

    //
    // copy the key
    //

    pdest = (PBYTE)&(pKey->KeyData[0]);

    switch (pKey->KeyType)
    {
    case DvdTitleKey:

        pKey->KeyFlags = pTitle->cgms;
        
        dwTmp--;

        psrc = (PBYTE)&(pTitle->title[0]);
        pdest = (PBYTE)&(pKey->KeyData[0]);
        break;

    case DvdAGID:

        pKey->SessionId = ((PRKFMT_AGID)pTitle)->agid >> 6;

        dwTmp = 0;

        break;

    default:

        psrc = (PBYTE)&(pTitle->cgms);
        pdest = (PBYTE)&(pKey->KeyData[0]);

        break;

    } // end switch on key type

    for (;dwTmp >0; dwTmp--)
    {
        *pdest++ = *psrc++;
    }
    
    return(TRUE);
}


DWORD CDisk::DVDReadKey(PIOREQ pIOReq)
{
    DWORD dwError = ERROR_SUCCESS;
    SGX_BUF SgBuf;
    ATAPI_COMMAND_PACKET    CmdPkt;
    PDVD_COPY_PROTECT_KEY pKey = (PDVD_COPY_PROTECT_KEY)pIOReq->pInBuf;
    DWORD dwLength;
    RKFMT_DISC keyBuf;
    DWORD dwRet;

    memset( &CmdPkt, 0, sizeof(ATAPI_COMMAND_PACKET));
    
    if (pIOReq->dwCode ==  IOCTL_DVD_START_SESSION) {
        pKey->KeyType = DvdAGID;
        // TODO: Add Region check here !!!
        dwLength = DVDSetupReadTitleKey( &CmdPkt, DvdAGID, 0, 0);
    } else {
        dwLength = DVDSetupReadKey(&CmdPkt, pKey);
    }    
    
    if (dwLength > pKey->KeyLength) {
        DEBUGMSG(ZONE_ERROR, (TEXT("cdReadKey illegal key request\r\n")));
        return (ERROR_INVALID_PARAMETER);
    }
    
    SgBuf.sb_len = dwLength;
    SgBuf.sb_buf = (PBYTE) &keyBuf;
    
    if (AtapiSendCommand(&CmdPkt)) {
        if (AtapiReceiveData(&SgBuf, 1, &dwRet)) {
            CopyDVDKey(dwLength, pKey, (PRKFMT_TITLE)&keyBuf);
        } else {
            DEBUGMSG( ZONE_ERROR|ZONE_CDROM, (TEXT("Atapi:DVDReadKey failed on recieve\r\n")));
            dwError = ERROR_READ_FAULT;
        }        
    } else {
        dwError = ERROR_GEN_FAILURE;
    }    
    return dwError;
}

//      Transfers the region and copy protect information to the client

DWORD CDisk::DVDGetRegion(PIOREQ pIOReq)
{
    DWORD dwError = ERROR_SUCCESS;
    DWORD dwLength;
    SGX_BUF SgBuf;
    DWORD dwRet;
    RKFMT_RPC rpcData;
    PDVD_REGIONCE preg;
    ATAPI_COMMAND_PACKET    CmdPkt;

    memset( &CmdPkt, 0, sizeof(ATAPI_COMMAND_PACKET));
    preg = (PDVD_REGIONCE)MapPtrToProcess((LPVOID)pIOReq->pOutBuf, GetCallerProcess());

    DVDGetCopySystem(&(preg->CopySystem)); 
    if (m_dwDeviceFlags & DFLAGS_MEDIA_ISDVD) {
        memset( &CmdPkt, 0, sizeof(ATAPI_COMMAND_PACKET));

        dwLength = DVDSetupReadTitleKey(&CmdPkt, DvdGetRPC, 0, 0);
        
        SgBuf.sb_len = sizeof(RKFMT_RPC);
        SgBuf.sb_buf = (PBYTE) &rpcData;
        
        if (AtapiSendCommand(&CmdPkt)) {
            if (AtapiReceiveData(&SgBuf, 1, &dwRet)) {
                if (rpcData.ResetCounts & 0xc0) {
                    preg->SystemRegion = rpcData.SystemRegion ^ 0xff;
                    preg->ResetCount = rpcData.ResetCounts & 0x07;
                } else {
                    // TODO: This is a virgin drive.  Should we set the region ??? 
                    // TODO: For now send back the default region
                    DEBUGMSG( ZONE_ERROR|ZONE_CDROM, (TEXT("Atapi:Brand new drive !!!\r\n")));
                    preg->SystemRegion = (BYTE)DEFAULT_DECODER_REGION;
                    preg->ResetCount = 0;
                }
            } else {
                DEBUGMSG( ZONE_ERROR|ZONE_CDROM, (TEXT("Atapi:DVDGetRegion failed on recieve\r\n")));
                dwError = ERROR_READ_FAULT;
            }        
        } else {
          // Probably a RPC I Drive        
            preg->SystemRegion = (BYTE)DEFAULT_DECODER_REGION;
            preg->ResetCount = 0;
        }    
    }    
    return dwError;
}


DWORD DVDSetupSendKey(ATAPI_COMMAND_PACKET *pCmd, PDVD_COPY_PROTECT_KEY pKey, RKFMT_CHLGKEY * keyBuf)
{
    BYTE KeyType;
    BYTE agid;
    DWORD dwRet;
    DWORD dwTmp;
    PRKCDB pcdb = (PRKCDB)pCmd;
    PVOID pdata = &(pKey->KeyData[0]);


    KeyType = (BYTE)pKey->KeyType;
    agid = (BYTE)pKey->SessionId;

    pcdb->OpCode = DVDOP_SEND_KEY;
    pcdb->Lun = 0;
    pcdb->KeyFmt = (agid << 6) | KeyType;

    if (!KeyType || KeyType > DvdBusKey2 || (pKey->KeyLength <
            ((dwRet = rkret[KeyType]) >> 24)))
    {
        return(0);
    }

    keyBuf->Len = (WORD)((dwRet >> 16) - (2 << 8));
    keyBuf->Reserved[0] = keyBuf->Reserved[1] = 0;

    if (KeyType == DvdBusKey2)
    {
        for (dwTmp = 0;dwTmp < 5;dwTmp++ )
        {
            *((PBYTE)(&keyBuf->chlgkey) + dwTmp) = *((PBYTE)pdata + dwTmp);
        }

        for (;dwTmp < 8; dwTmp++)
        {
            *((PBYTE)(&keyBuf->chlgkey) + dwTmp) = 0;
        }
    }
    else
    {
        for (dwTmp = 0;dwTmp < ((dwRet >> 26) - 1);dwTmp++ )
        {
            *((PDWORD)(&keyBuf->chlgkey) + dwTmp) = *((PDWORD)pdata + dwTmp);
        }
    }


    //
    // set up endian swapped allocation length, and clear reserved
    //

    *(PDWORD)(&pcdb->Reserved) = dwRet;
    
    pcdb->LBA = 0;

    pcdb->NACA = 0;

    return(EndSwap(dwRet));
}


DWORD CDisk::DVDSendKey(PIOREQ pIOReq)
{
    DWORD dwError = ERROR_SUCCESS;
    ATAPI_COMMAND_PACKET    CmdPkt;
    PDVD_COPY_PROTECT_KEY pKey = (PDVD_COPY_PROTECT_KEY)pIOReq->pInBuf;
    DWORD dwLength;
    RKFMT_CHLGKEY keyBuf;
    SGX_BUF SgBuf;
    DWORD dwRet;

    memset( &CmdPkt, 0, sizeof(ATAPI_COMMAND_PACKET));

    if (pIOReq->dwCode ==  IOCTL_DVD_END_SESSION) {
        BYTE bAgid;
        pKey->KeyType = DvdAGID;
        bAgid= (BYTE)pKey->SessionId;
        if (bAgid == -1)
            bAgid = 0;

        dwLength = DVDSetupReadTitleKey(&CmdPkt, -1, bAgid, 0);
    } else {
        dwLength  = DVDSetupSendKey(&CmdPkt, pKey, &keyBuf);
    }

    SgBuf.sb_len = dwLength;
    SgBuf.sb_buf = (PBYTE) &keyBuf;

    if (AtapiSendCommand(&CmdPkt)) {
        if (!AtapiSendData(&SgBuf, 1, &dwRet)) {
            DEBUGMSG( ZONE_ERROR|ZONE_CDROM, (TEXT("Atapi::DVDSendKey Failed\r\n")));
            dwError = ERROR_WRITE_FAULT;
        }
    } else {
      dwError = ERROR_GEN_FAILURE;
    }    

    return dwError;
}

DWORD CDisk::DVDSetRegion(PIOREQ pIOReq)
{
    // TODO: Implement Me
    return ERROR_NOT_SUPPORTED;
}

BOOL CDisk::DVDGetCopySystem(LPBYTE pbCopySystem) 
{   
    BOOL fSuccess = TRUE;
    ATAPI_COMMAND_PACKET    CmdPkt;
    PRDVDCDB  pCmd = (PRDVDCDB)&CmdPkt;
    RDVDFMT_Copy fmtCopy;
    SGX_BUF SgBuf;
    DWORD dwRet;
    
    memset( &CmdPkt, 0, sizeof(ATAPI_COMMAND_PACKET));

    pCmd->OpCode= DVDOP_READ_DVD_STRUC;
    pCmd->Format= DVDSTRUC_FMT_COPY;
    pCmd->Len = sizeof (RDVDFMT_Copy) << 8;         //Endian Swap the length
//    pCmd->Len = keyLength << 8;

    SgBuf.sb_len = sizeof(RDVDFMT_Copy);
    SgBuf.sb_buf = (PBYTE) &fmtCopy;


    m_dwDeviceFlags &= ~DFLAGS_MEDIA_ISDVD;

    if (AtapiSendCommand(&CmdPkt)) {
        if (AtapiReceiveData(&SgBuf, 1, &dwRet)) {
             *pbCopySystem = (BYTE)(fmtCopy.Data);
        }    
    } else {
        fSuccess = FALSE;
    }
    return fSuccess;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -