📄 dvdioctl.cpp
字号:
"Atapi!CSHXDiskAndCD::DVDGetRegion> %u user-controlled changes available\r\n" \
), x.ResetCounts & 0x07)); \
DEBUGMSG(ZONE_ERROR|ZONE_CDROM, (_T( \
"Atapi!CSHXDiskAndCD::DVDGetRegion> Region mask=%u\r\n" \
), x.SystemRegion ^ 0xFF)); \
DEBUGMSG(ZONE_ERROR|ZONE_CDROM, (_T( \
"Atapi!CSHXDiskAndCD::DVDGetRegion> RPC Scheme=%u\r\n" \
), x.RPCVer));
#else
#define DUMP_REPORT_KEY(x)
#endif
DWORD
CSHXDiskAndCD::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));
// map address and check for security violation
preg = (PDVD_REGIONCE)MapCallerPtr((LPVOID)pIOReq->pOutBuf, sizeof(BYTE));
if (pIOReq->pOutBuf != NULL && preg == NULL) {
// security violation
DEBUGMSG(ZONE_ERROR, (TEXT(
"Atapi!CSHXDiskAndCD::DVDGetRegion> Failed to map pointer to caller\r\n"
)));
return ERROR_INVALID_PARAMETER;
}
// read disc copy system and region
DVDGetCopySystem(&(preg->CopySystem), &(preg->RegionData));
memset(&CmdPkt, 0, sizeof(ATAPI_COMMAND_PACKET));
// create command packet to read RPC setting (report key)
dwLength = DVDSetupReadTitleKey(&CmdPkt, DvdGetRPC, 0, 0);
SgBuf.sb_len = sizeof(RKFMT_RPC);
SgBuf.sb_buf = (PBYTE) &rpcData;
// send command
if (AtapiSendCommand(&CmdPkt)) {
// fetch result
if (AtapiReceiveData(&SgBuf, 1, &dwRet)) {
DUMP_REPORT_KEY(rpcData);
// is the drive in a non-NONE RPC state?
if (rpcData.ResetCounts & 0xc0) {
// the drive is in SET, LAST CHANCE or PERM, i.e., this drive
// has had its region set already
preg->SystemRegion = rpcData.SystemRegion ^ 0xFF;
preg->ResetCount = rpcData.ResetCounts & 0x07;
}
else {
// the drive is in NONE, i.e., this drive is a virgin
DEBUGMSG(ZONE_ERROR|ZONE_CDROM, (_T(
"Atapi!CSHXDiskAndCD::DVDGetRegion> Region has never been set\r\n"
)));
preg->SystemRegion = 0xFF;
preg->ResetCount = 5;
}
}
else {
DEBUGMSG(ZONE_ERROR|ZONE_CDROM, (TEXT(
"Atapi!CSHXDiskAndCD::DVDGetRegion> Failed to receive REPORT KEY response\r\n"
)));
dwError = ERROR_READ_FAULT;
}
}
else {
DEBUGMSG(ZONE_ERROR|ZONE_CDROM, (TEXT(
"Atapi!CSHXDiskAndCD::DVDGetRegion> Failed to send REPORT KEY command\r\n"
)));
dwError = ERROR_READ_FAULT;
}
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);
}
}
*(PDWORD)(&pcdb->Reserved) = dwRet;
pcdb->LBA = 0;
pcdb->NACA = 0;
return (EndSwap(dwRet));
}
DWORD
CSHXDiskAndCD::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 (IOCTL_DVD_END_SESSION == pIOReq->dwCode) {
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!CSHXDiskAndCD::DVDSendKey> Failed to execute command %d\r\n"
), CmdPkt.Opcode));
dwError = ERROR_WRITE_FAULT;
}
}
else {
dwError = ERROR_GEN_FAILURE;
}
return dwError;
}
DWORD
CSHXDiskAndCD::DVDSetRegion(
PIOREQ pIOReq
)
{
return ERROR_NOT_SUPPORTED;
}
/*
CSHXDiskAndCD::DVDGetRegion
Return a bitfield which describes the regions in which the mounted
disc can be played.
Return
Success.
Notes
READ DVD STRUCTURE Data Format with Format field DVDSTRUCT_FMT_COPY
returns the Region Management Information, which describes the regions
in which the disc can be played. Each bit represents one of eight
regions. If a bit is cleared in this field, the disc can be played in
the corresponding region. If a bit is set in this field, the disc can
not be played in the corresponding region.
We perform an XOR with this field.
For more information on the READ DVD STRUCTURE command, see SFF8090i v5
R0.10, 13.25.
The READ DVD STRUCTURE with Format field = 0x01 return data is of the
following form:
Byte 0 DVD STRUCTURE Data Length (MSB)
Byte 1 DVD STRUCTURE Data Length (LSB)
Byte 2 Reserved
Byte 3 Reserved
Byte 4 Copyright Protection System Type
Byte 5 Region Management Information
Byte 6 Reserved
Byte 7 Reserved
*/
BOOL
CSHXDiskAndCD::DVDGetCopySystem(
LPBYTE pbCopySystem,
LPBYTE pbRegionManagement
)
{
BOOL fSuccess = FALSE;
ATAPI_COMMAND_PACKET CmdPkt;
PRDVDCDB pCmd = (PRDVDCDB)&CmdPkt;
RDVDFMT_Copy fmtCopy;
SGX_BUF SgBuf;
DWORD dwRet;
DEBUGCHK(NULL != pbCopySystem);
DEBUGCHK(NULL != pbRegionManagement);
*pbCopySystem = 0;
*pbRegionManagement = 0;
memset(&CmdPkt, 0, sizeof(ATAPI_COMMAND_PACKET));
memset(&fmtCopy, 0, sizeof(RDVDFMT_Copy));
pCmd->OpCode = DVDOP_READ_DVD_STRUC;
pCmd->Format = DVDSTRUC_FMT_COPY;
pCmd->Len = sizeof (RDVDFMT_Copy) << 8; // endian swap length
// pCmd->Len = keyLength << 8;
SgBuf.sb_len = sizeof(RDVDFMT_Copy);
SgBuf.sb_buf = (PBYTE) &fmtCopy;
m_dwDeviceFlags &= ~DFLAGS_MEDIA_ISDVD;
// attempt to detect if media is present
if (!AtapiIsUnitReady()) {
DEBUGMSG(ZONE_ERROR|ZONE_CDROM, (_T(
"Atapi!CSHXDiskAndCD::DVDGetCopySystem> DVD not present\r\n"
)));
goto exit;
}
// fmtCopy is a struct of two DWORDs; we need to return 4th and 5th bytes
if (AtapiSendCommand(&CmdPkt)) {
if (AtapiReceiveData(&SgBuf, 1, &dwRet)) {
*pbCopySystem = (BYTE)(fmtCopy.Data & 0xFF); // 4th byte
*pbRegionManagement = (BYTE)((fmtCopy.Data >> 8) & 0xFF); // 5th byte
*pbRegionManagement = *pbRegionManagement ^ 0xFF; // supported regions are 1s
fSuccess = TRUE;
}
}
exit:;
return fSuccess;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -