Microsoft DirectX 8.0

DVD リージョン変更サポート (Windows)

はじめに

ここでは、DVD リージョン選択プロセスが Microsoft® Windows® 9x および Windows 2000 上でどのように動作するかについて述べる。最初に、DVD リージョン情報の 3 つのソースについて説明する。次に、PC システム メーカーがシステムの初期 DVD リージョンをどのように設定するかを説明する。最後に、DVD ナビゲータがドライブ、デコーダ、およびディスク間でどのようにリージョンの一致を決定するかについて説明する。ここでは、アプリケーションおよびデコーダの開発者がコード内に適切な DVD リージョン選択サポートをどのように実装するかを示す。

DVD リージョン情報のソース

DVD リージョン情報にはソースが 3 つあり、Windows PC 上の DVD の再生に対するリージョンはこのすべてのソースによって決定される。

Windows 98 および Windows 2000 において初期リージョンを設定する方法

PC の DVD ドライブに対する初期 DVD リージョンを選択するのは、システム メーカーの役割である。

Microsoft DVD ナビゲータによって実行されること

Microsoft DVD ナビゲータは以下の方法を使用して、PC 上で DVD ディスクを再生中にリージョンの一致を確認する。

DVD ナビゲータはディスクのリージョン、ドライバのリージョン、およびデコーダのリージョンを取得する。ディスクのリージョンが "すべてのリージョン" である場合、DVD ナビゲータはディスクを再生する。ディスクにすべてのリージョンに対するマークが付いていない場合、DVD ナビゲータはデコーダにあらかじめ設定されたリージョンがあるかどうかを確認する。デコーダにあらかじめリージョンが設定されており、それがディスクのリージョンと一致しない場合は、DVD ナビゲータはエラーを返し、現在の DVD の設定ではディスクを再生できないということを示す。デコーダのリージョンがディスクのリージョンと同じ場合、DVD ナビゲータはドライブのリージョンがディスクのリージョンと同じかどうかを確認する。同じであれば、DVD ナビゲータはタイトルを再生する。同じでない場合は、DVD ナビゲータはドライブのリージョンを変更するためのコードを呼び出す。使用できるリージョン番号が残っていない場合、リージョン変更の試みは失敗し、そのシステム上でタイトルを再生できない。

次の DVD リージョンの変更

Windows 9x の場合、DVD ナビゲータは DVD ドライブ上でのリージョンの変更が必要であることがわかると、DVDRgn.exe を使用してドライブ上のリージョンの変更を要求する。このアプリケーションは、オペレーティング システムの他のコンポーネントと合わせてリージョナライズされる。このアプリケーションは、Windows 98 にデフォルトではインストールされていない。対象となるシステムへのインストールの方法を以下に示す。

Windows 2000 の場合、DVD ナビゲータは DVD マネージャで DVD-ROM ドライブ デバイス上のプロパティ ページを呼び出す。リージョンを変更する必要がある場合は、DVDPlay.exe アプリケーションによってもプロパティ ページが呼び出される。プロパティ ページの UI は DVDRgn.exe の UI によく似ており、オペレーティング システムによってリージョナライズされる。

RPC1 ドライブの場合、Windows オペレーティング システムのコンポーネントがリージョンの変更を管理する。RPC2 ドライブでは、リージョン設定はハードウェア自体に保持される。使用できる変更番号が RPC2 ドライブ上に残っていない場合、ドライブはリージョン変更の呼び出しに失敗し、そのことはオペレーティング システム内のリージョン変更コンポ-ネントによってユーザーに示される。

Windows リージョン変更サポート コンポーネントのインストール

アプリケーション開発者は Windows に組み込まれた DVD リージョン変更サポートを使用して、DVD 再生アプリケーション内のリージョンを変更できる。Windows 9x および Windows 2000 プラットフォームにおいてこれを実行するには 2 つの方法がある。

リージョン変更サポートのアプリケーションへの統合

以下の関数は、デコーダまたは DVD アプリケーションにリージョン変更サポートを統合したい開発者に提供される。
/////////////////////////////////////////////////////////////////////
// ChangeDVDRegion : DVD ドライブのリージョンを変更する関数
//
// パラメータ :
//  In : hWnd - この関数を呼び出すアプリケーション
//             のウィンドウ ハンドル
//  Out : なし。
//
// 以下の値を返す :
//     TRUE : ドライブのリージョン変更が成功した場合
//     FALSE : リージョン変更が失敗した場合 (おそらく、
//          有効な DVD-V ディスクのあるドライブが見つからないため)。
/////////////////////////////////////////////////////////////////////
BOOL ChangeDVDRegion(HWND hWnd)
{
typedef BOOL (APIENTRY *DVDPPLAUNCHER) (HWND hWnd, CHAR DriveLetter);
BOOL   bRegionChanged = FALSE;
TCHAR   szCmdLine[MAX_PATH];

// まず、有効な DVD-V ディスクのある DVD ドライブはどれかを見つける。

TCHAR     szDVDDrive[4];
if (! GetDriveLetter (szDVDDrive) )
  {
MessageBox(hWnd, 
TEXT("No DVD drive was found with DVD-V disc.")
TEXT("\nCannot change DVD region of the drive."), 
TEXT("Error"), MB_OK | MB_INFORMATION) ;
return FALSE ;    
  }

// 実行中の OS を検出する。Windows NT の場合、storprop.dll を使用し、
// Windows 9x の場合は DVDRgn.exe アプリケーションを使用してリージョンを変更する。

OSVERSIONINFO   ver;
ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&ver);
if (VER_PLATFORM_WIN32_NT  == ver.dwPlatformId)
  {
// Windows NT プラットフォーム
HINSTANCE       hInstDLL;
DVDPPLAUNCHER    dvdPPLauncher;
CHAR         szDVDDriveA[4];

#ifdef UNICODE
WideCharToMultiByte(0, 0, szDVDDrive, -1,
szDVDDriveA, sizeof(szDVDDriveA),
NULL, NULL );
#else
strcpy(szDVDDriveA, szDVDDrive);
#endif  // UNICODE

GetSystemDirectory(szCmdLine, MAX_PATH);
lstrcat(szCmdLine, TEXT("\\storprop.dll"));
    
hInstDLL = LoadLibrary (szCmdLine);
if (hInstDLL)
    {
dvdPPLauncher = (DVDPPLAUNCHER) GetProcAddress(hInstDLL,
"DvdLauncher");
if (dvdPPLauncher)
      {
bRegionChanged = dvdPPLauncher(hWnd, szDVDDriveA[0]);
      }
FreeLibrary(hInstDLL);
    }
}  // Windows NT プラットフォーム用のリージョン変更コードの終わり
else   // Windows 9x プラットフォーム
  {
// コマンド ライン文字列用の \windows\dvdrgn.exe のパスを取得する
GetWindowsDirectory(szCmdLine, MAX_PATH);
lstrcat(szCmdLine, TEXT("\\DVDRgn.exe "));

// コマンド ライン パラメータとしてドライブ レターのみ追加する
lstrncat(szCmdLine, szDVDDrive, 1);
    
// DVDRgn.exe 実行の準備をする
STARTUPINFO               StartupInfo;
PROCESS_INFORMATION       ProcessInfo;
StartupInfo.cb            = sizeof(StartupInfo);
StartupInfo.dwFlags       = STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow   = SW_SHOWNORMAL;
StartupInfo.lpReserved    = NULL;
StartupInfo.lpDesktop     = NULL;
StartupInfo.lpTitle       = NULL;
StartupInfo.cbReserved2   = 0;
StartupInfo.lpReserved2   = NULL;
if (CreateProcess(csModuleName, szCmdLine, 
NULL, NULL, TRUE, 
NORMAL_PRIORITY_CLASS,
NULL, NULL, &StartupInfo, &ProcessInfo) )
    {
// DVDRgn.exe が終了するまで待つ
WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
DWORD dwRet = 1;
BOOL bRet = GetExitCodeProcess(ProcessInfo.hProcess,
&dwRet);
// ユーザーがドライブのリージョン変更に成功した場合、
// DVDRgn.exe の終了コードは 0。
if (bRet && 0 == dwRet)  
      {
bRegionChanged = TRUE;
      }
    }
}  // Windows 9x プラットフォーム用のリージョン変更コードの終わり

if (bRegionChanged)   // リージョンの変更が成功した場合
  {
// 古いフィルタ グラフを削除して新しいフィルタ グラフを作成するために、
// IDvdGraphBuilder::RenderDvdVideoVolume() を使用する。
  }
else   // DVD リージョンがなかった
  {
MessageBox(hWnd, 
TEXT("DVD drive region could not be changed.")
TEXT("Error"), MB_OK | MB_INFORMATION) ;
  }
} //関数 ChangeDVDRegion の終わり

/////////////////////////////////////////////////////////////////////
// GetDriveLetter : 現在アクティブなドライブのドライブ レターを 
//           取得する関数
// パラメータ :
//  In : pDvdC - DVDNavigator フィルタの IDvdControl 
//                インターフェイスへのポインタ..
//  Out : pszDrive - 有効な DVD-V ディスクがあることがわかった、
//                  最初の DVD ドライブ。
//
// 以下の値を返す :
//     TRUE : DVD ドライブが検出された場合 (有効なディスクと共に)
//     FALSE : 有効な DVD-V ディスクのある DVD ドライブが検出されなかった場合。
/////////////////////////////////////////////////////////////////////
BOOL GetDriveLetter(IDvdControl *pDvdC, TCHAR *pszDrive) 
{
CHAR   szPathA[MAX_PATH];
TCHAR   szPath[MAX_PATH];
ULONG   ulActualSize;
pszDrive[0] = pszDrive[3] = 0;

// 現在のルート ディレクトリを取得する
if (pDvdC ->GetRoot(szPathA, MAX_PATH, &ulActualSize))
  {
#ifdef UNICODE
MultiByteToWideChar(CP_ACP, 0, szPathA, 0, szPath, MAX_PATH);
#else
lstrcpy(szPath, szPathA);
#endif  // UNICODE
lstrcpyn(pszDrive, szPath, 3);
if (DRIVE_CDROM == GetDriveType(pszDrive)) // DVD ドライブ の場合
return TRUE;
  }

// 有効なドライブ全体をループして、有効な DVD-V ディスクが入っている
// DVD ドライブはどれかを見つける。

// 有効なドライブをすべて取得する
DWORD dwLeng = GetLogicalDriveStrings(MAX_PATH, szPath);
TCHAR  *pszTemp = szPath;
// すべてのドライブを 1 つずつ試す
for (DWORD dw = 0; dw < dwLeng; dw += 4) 
  {
// 必要な (.ifo) ファイルを持つ CD-ROM ドライブのみ調べる
if (DRIVE_CDROM  == GetDriveType(pszTemp)) 
      {
TCHAR   szDVDPath1[MAX_PATH]
TCHAR   szDVDPath2[MAX_PATH];
lstrcpyn(szDVDPath1, pszTemp, 4);
lstrcpyn(szDVDPath 2, pszTemp, 4);
lstrcat(szDVDPath1, TEXT("Video_ts\\Video_ts.ifo"));
lstrcat(szDVDPath2, TEXT("Video_ts\\Vts_01_0.ifo"));

//  .ifo ファイルがドライブ上にある場合、それは有効な DVD-V ディスクを持っている
if (DoesFileExist(achDVDPath1) && DoesFileExist(achDVDPath2))    
        {
lstrcpyn(pszDrive, pszTemp, 3);
return TRUE;   // 有効な DVD-V ディスクを持っている最初のドライブを返す
        }
      }
pszTemp += 4; 
  }

return FALSE ;   // DVD ドライブ (DVD-V コンテンツを含む) が見つからなかった。
} //関数 GetDriveLetter の終わり

/////////////////////////////////////////////////////////////////////
// DoesFileExist : 特定のファイル名が既存のファイルであるかどうかを確認する関数。
//
// パラメータ :
//  In : pszFile - 存在を確認するファイル名の文字列
//  Out : なし。
//
// 以下の値を返す :
//     TRUE : 指定されたファイルが見つかった場合。
//      FALSE : 指定されたファイルが見つからなかった場合。
/////////////////////////////////////////////////////////////////////
BOOL DoesFileExist(LPTSTR pszFile)
{
HANDLE    hFile = NULL ;
// 必要なファイルを開いて読むことができるかどうかテストを試みる場合に、
// エラー メッセージ ボックスが表示されないようにしたい。

UINT uErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS | 
SEM_NOOPENFILEERRORBOX);
hFile = CreateFile(pszFile, GENERIC_READ, 
FILE_SHARE_READ, NULL, 
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
SetErrorMode(uErrorMode);  // エラー モードを回復する。
If (INVALID_HANDLE_VALUE  == hFile) 
return FALSE ;    

CloseHandle(hFile);
return TRUE;
} //関数 DoesFileExist の終わり