|開発環境|Microsoft Visual C++ 2010 Express (SP1)| |実行環境|Microsoft Windows XP Home Edition (SP3)| |プロジェクトの種類|Win32 コンソール アプリケーション| |プロジェクト名|readtoc| |アプリケーションの種類|コンソール アプリケーション| |追加のオプション|空のプロジェクト| |文字セット|Unicode| Windows Driver Kit Version 7.1.0 参考 -[[TOCの取得>http://www2.muroran-it.ac.jp/circle/mpc/front/old1/program/windows/spti_cdda/spti04.html]] readtoc.cpp #highlight(cpp){{ /* [構成プロパティ]-[VC++ ディレクトリ]-[インクルード ディレクトリ] C:\WinDDK\7600.16385.1\src\storage\tools\spti Unicode文字セット */ #include <Windows.h> #include <tchar.h> #include <locale.h> #include <stddef.h> #include <ntddscsi.h> #include <spti.h> #define REVWORD(w) (((w<<8)&0xff00)|((w>>8)&0xff)) #define REVDWORD(dw) (((dw<<24)&0xff000000)|((dw<<8)&0xff0000)|((dw>>8)&0xff00)|((dw>>24)&0xff)) struct READTOC { WORD wLen; BYTE byStartTrack; BYTE byEndTrack; struct TRACKDESC { BYTE d0; BYTE data; BYTE byTrack; BYTE d1; DWORD dwLBA; } td[100]; }; // 関数プロトタイプ宣言 int TrackList(TCHAR cDrv); DWORD ExecCommand( HANDLE hDev, // デバイスハンドル PUCHAR pucCdb, // コマンド(SCSI command descriptor block) UCHAR ucCdbLen, // コマンドの長さ PVOID pvData, // バッファ ULONG ulDataLen); // バッファの長さ //============================================================================== int _tmain(int argc, LPTSTR argv[]) { TCHAR szDrv[] = _T("@:\\"); UINT ur; _tsetlocale(LC_CTYPE, _T("")); if (argc != 2) { _ftprintf(stderr, _T("usage: readtoc drive\n")); return 1; } szDrv[0] = argv[1][0]; ur = GetDriveType(szDrv); if (ur != DRIVE_CDROM) { _ftprintf(stderr, _T("CD-ROMドライブではありません。\n")); return 1; } TrackList(szDrv[0]); return 0; } //------------------------------------------------------------------------------ int TrackList(TCHAR cDrv) { int nRet = 0; // デバイスのオープン TCHAR szDev[] = _T("\\\\.\\@:"); HANDLE hDev; BOOL br; szDev[4] = cDrv; hDev = CreateFile(szDev, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hDev == INVALID_HANDLE_VALUE) { return -1; } // TOC BYTE byBuf[sizeof (READTOC) + 0xf]; // パラグラフ境界 READTOC *ptoc = (READTOC *)(((UINT_PTR)byBuf + 0xf) & ~0xf); UCHAR ucCdb[10]; DWORD dw; ZeroMemory(ptoc, sizeof *ptoc); ZeroMemory(ucCdb, sizeof ucCdb); ucCdb[0] = SCSIOP_READ_TOC; ucCdb[6] = 1; *(PWORD)(ucCdb + 7) = REVWORD(sizeof *ptoc); dw = ExecCommand(hDev, ucCdb, sizeof ucCdb, ptoc, sizeof *ptoc); if (dw == 0) { nRet = -1; goto Exit; } // トラック一覧 BYTE by; _tprintf(_T("Track\tAttr\tLBA\tLen\n")); for (by = 0; by < ptoc->byEndTrack; by++) { BYTE byData = ptoc->td[by].data; DWORD dwStartAddr = REVDWORD(ptoc->td[by].dwLBA); DWORD dwEndAddr = REVDWORD(ptoc->td[by+1].dwLBA) - 1; DWORD dwLen = dwEndAddr - dwStartAddr + 1; _tprintf(_T("%2u\t%#4x\t%6u\t%6u\n"), by+1, byData, dwStartAddr, dwLen); } Exit: br = CloseHandle(hDev); return nRet; } //------------------------------------------------------------------------------ DWORD ExecCommand( HANDLE hDev, // デバイスハンドル PUCHAR pucCdb, // コマンド(SCSI command descriptor block) UCHAR ucCdbLen, // コマンドの長さ PVOID pvData, // バッファ ULONG ulDataLen) // バッファの長さ { SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb; DWORD dwRet; BOOL br; ZeroMemory(&swb, sizeof swb); swb.sptd.Length = sizeof swb.sptd; // swb.sptd.CdbLength = ucCdbLen; swb.sptd.SenseInfoLength = sizeof swb.ucSenseBuf; swb.sptd.DataIn = SCSI_IOCTL_DATA_IN; swb.sptd.DataTransferLength = ulDataLen; swb.sptd.TimeOutValue = 10; // 秒 swb.sptd.DataBuffer = pvData; swb.sptd.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf); memcpy_s(&swb.sptd.Cdb, sizeof swb.sptd.Cdb, pucCdb, ucCdbLen); br = DeviceIoControl( hDev, IOCTL_SCSI_PASS_THROUGH_DIRECT, &swb, sizeof swb, &swb, sizeof swb, &dwRet, NULL); if (br == FALSE) { return 0; } return dwRet; } }} 出力 Track Attr LBA Len 1 0x10 37 5375 2 0x10 5412 29128 3 0x10 34540 16385 4 0x10 50925 5242 5 0x10 56167 5330 6 0x10 61497 11800 7 0x10 73297 15910 8 0x10 89207 16218 9 0x10 105425 5357 10 0x10 110782 8218 11 0x10 119000 11050 12 0x10 130050 21600 13 0x10 151650 18567 14 0x10 170217 7825