
Introduction
I've been playing with DVDs recently and stumbled upon many tools for DVD backup, DVD region-free tools, and such. In this article we are going to demonstrate how to programmatically retrieve the DVD's region information.
What is DVD Region?
In short it is a mechanism encoded both in DVD players and on DVD discs dictating if a DVD player can play a certain DVD disk. The DVD region in the DVD player is stored inside the hardware and cannot be reset if windows is re-installed or the player was moved to another PC. Some ways to circumvent this is to update your player's firmware and remove the DVD region support from it. The DVD region in the DVD movie is stored inside one of its IFO file.
From [1] we have the following regions:
Region Code | Region Name |
0 | No Region Coding |
1 | United States of America, Canada |
2 | Europe, including France, Greece, Turkey, Egypt, Arabia, Japan and South Africa |
3 | Korea, Thailand, Vietnam, Borneo and Indonesia |
4 | Australia and New Zealand, Mexico, the Caribbean, and South America |
5 | India, Africa, Russia and former USSR countries |
6 | Peoples Republic of China |
7 | Unused |
8 | Airlines/Cruise Ships |
9 | Expansion (often used as region free) |
DVD region has been defined extensively on the net please check this article's references.
Technical prerequisites
In order to read information from the DVD drive we are going to issue SCSI commands to the hardware itself (DVD player). For simplicity, this article's code do not use ASPI instead uses Microsoft's SPTI (SCSI Pass Through Interface) to talk with the hardware. The SCSI commands issued to the hardware are standards and can be found on the net [
3].
Using SPTI to issue SCSI commands
Sending SCSI / CDBs (command descriptor blocks) to the device is very simple with the SPTI interface and consists of only setting up the correct block and sending it.
- Open the device, say: \\.\C:\
- Prepare a
SCSI_PASS_THROUGH_DIRECT
structure
- Prepare the CDB (Command Descriptor Block), a structure used to select which command and pass appropriate parameters ([4] [6])
- Prepare the return or data buffer (buffer returned after the command is issued)
- Use
DeviceIoControl()
with IOCTL code value of IOCTL_SCSI_PASS_THROUGH_DIRECT
(value 0x4D014) to issue the call
- Interpret the results
Reading the DVD region
After reading in [5] we realize that we need to send to the DVD the SCSI operation code SCSIOP_REPORT_KEY
(value 0xA4) with some specific parameters.
The REPORT_KEY can be used to do many things, but we only need to read the DVD region information, for that we fill the "CDB_REPORT_KEY
" as:
OperationCode = SCSIOP_REPORT_KEY
AllocationLength = sizeof(REPORT_KEY_DATA_RPC_STATE)
AGID = 0
KeyFormat = KEY_FORMAT_RPC_STATE
After the command is issued, a REPORT_KEY_DATA_RPC_STATE
([5] page 533) will be filled with the region information.
Quoted and paraphrased from [5]:
# of Vendor Resets Available = is a count down counter that indicates the number of times that the vendor may reset the region. The manufacturer of the Drive sets this value to 4 and the value is decremented each time the vendor clears the Drive’s region. When this value is zero, the vendor may no longer clear the Drive's region.
# of User Controlled Changes Available = is a count down counter that indicates the number of times that the user may set the region. This value is initially 5.
The Region Mask returns a value that specifies the Drive Region in which the Drive is located. Once the Drive Region has been set, the Drive shall be located in only one region. Each bit represents one of eight regions. If a bit is cleared in this field, the disc may be played in the corresponding region. If a bit is set in this field, the disc may not be played in the corresponding region. Only one bit can be cleared.
Example: if region mask is 0xFE which is 11111110 in binary means that bit1 is cleared thus region 1 is set.
RPC Scheme specifies the type of Region Playback Controls being used by the Drive.
We currently have two schemes RPC1 which do not enforce region playback control, and RPC2 which enforces the region playback control.
The code
void print_region_info(HANDLE device)
{
static char *region_names[] =
{
"United States of America, Canada",
"Europe, including France, Greece, Turkey, Egypt, Arabia, "
"Japan and South Africa",
"Korea, Thailand, Vietnam, Borneo and Indonesia",
"Australia and New Zealand, Mexico, the Caribbean, and South America",
"India, Africa, Russia and former USSR countries",
"Peoples Republic of China",
"Unused",
"Airlines/Cruise Ships"
};
static char *region_set[] =
{
"No region set",
"Region set",
"Drive region is set. Additional restrictions required to make changes",
"Region set permanently, but may be reset by vendor",
};
REPORT_KEY_DATA_RPC_STATE region = {0};
CDB_REPORT_KEY report = {0};
report.OperationCode = SCSIOP_REPORT_KEY;
report.AllocationLength = sizeof(REPORT_KEY_DATA_RPC_STATE);
report.AGID = 0;
report.KeyFormat = KEY_FORMAT_RPC_STATE;
if (!carry_cdb(device, &report, sizeof(report), ®ion, sizeof(region)))
{
printf("Could not get region info!\n");
return;
}
unsigned char region_code = ~region.region_mask;
int i;
char *region_name = "No Region Coding";
for (i=7;i>=0;i--)
{
if ( (1 << i) & region_code)
{
region_name = region_names[i];
break;
}
}
printf(
"Region Information:\n"
"-------------------\n"
"Vendor changes: %d\n"
"User changes: %d\n"
"Region name: %s\n"
"Type code: %s\n",
region.nb_vendor_resets,
region.nb_user_changes,
region_name,
region_set[region.type_code]
);
}
How to programmatically set DVD region?
I did not try it, but apparently one has to issue a
SEND_KEY
command with appropriate structures. Check [
5] page 587.
Conclusions
Hope you learned a little from this article and got pointers about where to look further.
If I find interest and time, perhaps I will extend my knowledge beyond this and write more articles. Meanwhile, happy coding.
References
- [1] http://www.hometheaterinfo.com/dvd3.htm
- [2] http://www.codefreedvd.com/dvd_dvdregionlockingexplained.htm
- [3] http://www.t10.org/
- [4] http://en.wikipedia.org/wiki/SCSI_CDB
- [5] T10.org [3] / SCSI Multi-Media Commands – 5 (MMC-5) / mmc5r03a.pdf
- [6] DDK / SCSI_PASS_THROUGH documentation