TabIe 26 Read TOC/PMA/ATIP コマンド 7 6 5 が使用可能であるかを知ることができ , 正 常に使用できる場合にのみ正常終了します。 CD-ROM ドライプや MO ドライプのよう なリムーバブルデノヾイスでは , メディアが 入っているときにのみ正常動作可能なので この 0 ンドを使用することでメディアカ : 挿入されていてアクセス可能であるかどう かを知ることができます。 トラックの検出 音楽 CD では , 楽曲は一般にトラック単 8 位で管理されており , 1 トラックが 1 曲に当 たります。音楽 CD ではこのほかにインデッ べンダユニーク コントロールバイト 9 クスというものもありますが , これはトラ ックのサプチャネル Q に書かれているだけ 番号と , 取得するデータ長 ( アロケーショ れるトラックの情報は , Table 26 のように で , 実際にトラックを読んでみないとわか ン長 ) を指定します。そうすると , 指定さ 位置情報と属性だけです。曲の長さを調べ らないものです。このようなトラックの開 れたトラック以降のトラック情報が指定し るには , そのトラックの開始アドレスと , 始アドレスを知るためには TOC 領域のデー たデータの長さぶんだけ取得できます。オ その次のトラックの開始アドレスとの差を タを読む必要があります。しかし , ーディオ CD では , 最大トラック数はリ 計算する必要があります。 こは 特殊な領域なので普通に読み出すことがで アウトトラックを合わせて 100 トラックなの なお , 取得するトラックのアドレスは LB きません。このため , 専用コマンドである で , 少なくとも 100 トラックぶんのバッファ A アドレスでも , MSF アドレスでも取得可 Read TOC (TabIe 26 ~ 32 ) を使用します。 を準備して Read TOC コマンドを発行すれ 能ですが , MSF アドレスでは曲長を計算す ReadTOC コマンドを発行するときは , 取 ば 1 回の実行だけですべてのトラック情報 るときなどに扱いにくいため , サンプルプ 得を開始するトラック情報の先頭トラック を取得することができます。このとき得ら ログラムではすべて LBA アドレスで取得し TabIe 27 Table 26 のバラメータの内容 バラメータ このビットが 1 のとき転送される TOC データのアドレス表現が MSF アドレス表現とする MSF MMC -2 準拠のドライブではここに以下の値をセットすることでいろいろな情報を取得することができる 値 内容 ソース 指定したトラックから , 各トラックの情報を取得する。マルチセッションディスクでは , す べてのセッションのトラックの情報を返しリードアウトトラックは最終確定セッションの TO C リードアウトトラックを返す 確定したセッションの開始セッション番号と終了セッション番号を取得する TO C 指定したセッションのリードイントラックすべての TOC のサプチャネル 0 を取得する 0010b TO C PMA 領域のサプチャネル 0 のデータを取得する リサーブ 0011b PMA リードインエリアの AT 旧データを取得する リザーブ 0100b ATIP リードインエリアの CD - TEXT 情報を取得する リサーブ CD-TEXT 0101b その他 リザープ 開始トラック どのトラック ( 1 ~ ) から情報を取得するかを指定する。 0X00 を指定したときは , そのメディアの最初のトラック ( 必ずしも 1 から始まるとは 限らない ) にある TOC データから転送する。フォーマット 0010b のときは , TOC を取得したいセクションを指定する セクション アロケーション長 イニシェータが受け取れるデータバイト数を指定する SONY 互換コマンドを持つドライブでは , ここに Fo 「 mat の 00b.01 b , 10b の値をセットすることができる ( 返却される値も , 必要な設定も同 べンダユニーク じ ) 。このとき必ず Fo 「 mat は 0000b にしておくこと 3 オペレーションコード ( 0X43 ) Reserved 0 1 2 0 1 ・ワ」っ 0 4 ・広 0 ( 0 マ / MSF Format (MMC-2) LUN Reserved Rsved Reserved Reserved Reserved 開始トラック , またはセッション番号 (MSB) アロケーション長 (LSB) オフセット 6 の値 トラック 0000b FO 「 mat リザーブ 0001 b セッション 56 C MAGMINE 2001 11
ユーザ環境の取得 今回は , ユーザ環境の情報を取得するプログラムを作ってみます。ユーザがどのような環境の PC を利用しているかをアプリケーションレベルで知っておくことは , アプリケーションの動 作に大きな影響を与えられます。 しようが , プラウザというアプリケーショ も 50G バイトを超えるハードディスクドラ / ューザ環境の必要性 ンからの操作にその趣が変わってきている イプを積んでいるものが多数あります。プ のです。 ロードバンドという言葉に象徴されるよう メールに関しては , 若い世代では PC よ ューザ環境を取得することは , 俗にいう に動画や静止画 , 音声などのマルチメデ e - ビジネスには必要不可欠です。ターゲッ りも , 携帯電話を利用する人のほうが多い ィア情報を扱う機会が非常に多くなってき トになる環境ではどのような PC を使って かもしれません。日本では i モードは爆発的 ています。これらのマルチメディア情報を いるか ? どのくらいの処理能力のマシン なヒットになりましたが , 使う側はそれが 扱うには , 大容量のハードディスクが必須 を利用しているか ? 解像度やプラウザは インターネットの環境だということを知る なのです。大容量のデータを扱うアプリケ 何なのか ? このあたりの情報を元に , タ 必要はありません。あくまで便利だから , ーションでは , 常に空き容量などをチェッ ーゲットに合ったアプリケーションの開発 自分にとって必要だから使うのです。 クする必要も出てくるでしよう。 を行う必要があります。 こうなると , どんな環境からアクセスし ードディスクは , ここ数年でもっとも Web サイトでは , アクセス解析によって てどんな状況で利用しているのかをアプリ 進歩したパーツの 1 つになります。このこ 利用しているプラウザや OS などの判別が ケーションの作成者側が把握して , 状況に とから , 50G バイトを超えるハードディス できます。通常これらを利用してターゲッ 応じたインタフェイスなどを提供しなけれ クを実装しているマシンも多数あれば , 逆 トに合わせたコンテンツに Web サイトを変 ばならないのです。 に 10G バイト以下のハードディスクでがん 更していきますが , さらに突っ込んだ解析 ばっているマシンも多数あるということも ネットワーク環境の取得 がほしい場合も多々あります。このような あるのです。 場合 , 今回のサンプルのようにアプリケー 今回は , まずネットワーク環境を取得し メモリ情報の取得 ションレベルでその実態を把握しなければ ます。 IP アドレスの体系や DHCP サーノヾ利 用の有無またコンピュータ名などを取得 メモリ環境は , ハードディスクドライプ なりません。 などストレージの環境に比べれば進歩の少 しています。 多様化しているユーザ環境 ネットワークの構築には , いろいろな種 類や方法があります。インターネット全盛 Fig. 1 サンプルプログラムの動作画面 インターネットの存在が大きくなるにつ とはいえ , NetBEUI などの Wmdows の基本 れ , ユーザ側の環境が非常に多様化してき 的なプロトコルを使用して peertopeer で L ユーザー環境の収得 ています。 AN を構築している場合も数多くあります。 Wlndows NT コンヒュータを使うという言葉が , Win TCP/IP に依存したアプリケーションはこ Version 5.0 Service Pack 1 Build 2195 dows や Macintosh を使うということではな のような環境では動作しないので , 事前に ユーザーネーム Administrator H 0 n 訓 e VRX 状態を把握する必要があるのです。 く , インターネットを利用するということ 旧 Addres 127.0.0.1 トータルメモリ容量 245216 KB に変わっているようです。 PC の雑誌や街 また MAC アドレスなどを取得すること 利用中のメモリ物理容量 150636 KB C ドライプトータル 1 1 Gbyte C ドライブ空容量 1 Gbyfe 頭アンケートなどの結果を見ても , PC で で , 端末を限定することも可能です。 C ドライブ空容量 13657251 byte Disk S/N 日 e2d5a7 何をやるかの問いでいちばんに出てくるの ディスク情報の取得 はインターネットであり , メールでしよう。 Word などで文書を作ることも当然あるで 最近は , 20 万円以下で購入できる PC で 1 24 C MAGMINE 2001 11 tatsuya (tatsuya@exnet.com/ 第 22 回 0 MAGAZINE - し諷謬以ー Close
TabIe 2 今回利用した主な A 曰 int gethostname (char FAR * name. int namelen); 内容コンピュータ名を取得する name 引数 namelen ホスト名を格納するバッファ 上記バッフアサイズ 戻り値成功時は 0 , 失敗時は SOCKET ー E 日日 O 日のコード struct HOSTENT FAR *gethostbyname (const char FAR * name) : 内容ホストデータベースからホスト名の情報を取得する 引数 name ホスト名の文字列へのポインタ 成功時は HOSTENT 構造体へのポインタ , 失敗時は NULL0 HOSTENT 構造体は以下のとおり struct hostent ー cha 「 FAR * h_name; char FAR * FAR * h_aliases; short h—addrtype, short h 」 ength; char FAR * FAR * h_addr 」 ist; 戻り値 正式なホスト名 ホストの別名リスト アドレスの種類 アドレス長 アドレスのリスト int WSAStartup (WORD wVersionRequested, LPWSADATA lpWSAData) : 内容 WinSock の初期化。プロセスによって WinSock DLL の使用を始める wVersionRequested その呼び出し側が使うことができる WinSock のバ - ジョン lpWSAData 引数 WinSock の詳細を受け取る WSADATA 構造へのポインタ。 WSADATA 構造体は以下のとおり struct WSAData ー WORD wVersion; WORD wHighVersion; Cha 「 * szDesc 「 iption; cha 「 * szSystemStatus; unsigned short iMaxSockets; unsigned short iMaxUdpDg, char *IpVendorInfo; ー WSADATA, WinSock DLL で使用する WinSock のバージョン サポートする WinSock のバージョン番号 WinSock に関する情報の文字列 WinSock のステータス 1 つのプロセスで開けるソケットの最大数 送信可能なデータグラムの最大バイトサイズ WinSock のべンダ情報 返り値成功時は O , 失敗時は 0 以外 int WSACleanup (void) : 内容現在のスレッドのユーザ名を取得する BOOL GetUserName (LPTSTR lpBuffer, LPDWORD nSize) : 返り値成功時は 0 , 失敗時は SOCKET_ERROR 内容 WinSock のリソースを解放し WinSock DLL の使用を終了する lpBuffe 「 引数 nSize ユーザ名を格納するバッファ 上記バッフアサイズ 戻り値成功時は 0 以外の値 ( T 日 UE ) , 失敗時は 0 (FALSE) BOOL GetDiskFreeSpaceEx (LPCTSTR lpDi 「 ectoryName, PULARGE 」 NTEGER lpF 「 eeBytesAvailabIeTOCalIer. PULARGE 」 NTEGER lpTotalNumberOfBytes. PULARGE 」 NTEGER lpTotalNumberOfF 「 eeBytes) : 内容ディスク容量に関する情報を取得する IpDirectoryName 情報を取得するディスクのディレクトリ名。 UNC を使うこともできる IpFreeBytesAvaiIabIeTOCaIIer カレントユーザが利用できるディスクの空き容量を表す , PULARGE 」 NTEGER 型の IpT0talNumbe 「 OfBytes 引数 変数へのポインタ ティスクの総容量を表す . ULA 日 GE 」 NTEGE 日型の変数へのポインタ IpTotaINumbe 「 OfF 「 eeBytes ディスクの空き容量を表す , ULA 日 GE 」 NTEGE 日型の変数へのポインタ 戻り値成功時は 0 以外の値 ( T 日 UE ) , 失敗時は 0 (FALSE) BOOL GetVoIumelnformation (LPCTSTR lpRootPathName, LPTSTR lpVoIumeNameBuffe 「 , DWORD nVolumeNameSize, LPDWORD lpVolumeSeriaINumbe 「 , LPDWORD lpMaximumComponentLength. LPDWORD lpFileSystemFlags. LPTSTR lpFileSystemNameBuffer. DWORD nFileSystemNameSize) : 指定されたルートティレクトリのファイルシステムとボリュームの情報を取得する 内容 戻り値 引数 lpRootPathName IpVoIumeNameBuffe 「 nVolumeNameSize lpVoIumeSerialNumbe 「 ルートディレクトリ名の文字列へのポインタ ボリューム名を格納するバッフアへのポインタ IpVOIumeNameBuffe 「バッフアのサイズ ボリュームシリアル番号を格納する文字列へのポインタ lpMaximumComponentLength ファイルシステムがサポートするファイル名の最大長を格納する変数へのポインタ lpFiIeSystemFIags IpFiIeSystemNameBuffe 「 nFiIeSystemNameSize ファイルシステムのフラクを格納する変数へのポインタ。以下の値の組み合わせ FS_CASE 」 S_PRESERVED ディスクにファイル名を記録するときに大文字と 小文字を区別して保存する FS_CASE_SENSITIVE ファイル名の大文字と小文字の区別をサポートしている FS_UN ℃ ODE_STORED_ON_DISK UN ℃ ODE のファイル名をサポートしてい て , ディスク上でも正しく表示される FS_PERSISTENT_ACLS アクセス制御リストの保存と適用を行う FS_FILE_COMPRESSION ファイルべースの圧縮をサポートしている FS_VOL 」 S_COMPRESSED 指定されたボリュームが圧縮ボリューム FILE_NAMED_STREAMS 名前付きストリームをサポートしている FILE_SUPPORTS_ENCRYPTION 暗号化ファイルシステムをサポートしている FILE_SUPPORTS_OBJECT 」 DS オブジェクト識別子をサポートしている FILE_SUPPORTS_REPARSE_POINTS 再解析ポイントをサポートしている FILE_SUPPORTS_SPARSE_FILES スパースファイルをサポートしている FILE_VOLUME_QUOTAS ディスククオータをサポートしている ファイルシステム名を格納する文字列へのポインタ IpFileSystemNameBuffer バッフアのサイズ P 『 m 加 ります。工ラーの場合は , IP アドレスが割 り振られていないか DHCP サーバによって IP アドレスを割り振られる設定になってい ます。 ディスク情報の取得 ディスク情報は , 次のような流れで取得 します。 ①チェックしたいドライブ名を取得 ② GetDiskFreeSpaceEx API で空き容量 などを取得 ほかにも GetVolumeInformation API でポ リューム名やシリアル番号などを取得でき ます。また , GetDiskFreeSpace API でクラ スタ情報などを取得できます。今回のプロ グラムでは , List 1- ⑥のように C ドライプ に限定してディスク情報を取得しています。 返される値の単位はバイトです。 M バイ トや G ノヾイトなどで表示する場合は , 1024 で割らなければなりません。 シリアル番号は , List 1- ⑦のように GetV olumelnformation API から得ることができ ます。 メモリ情報の取得 メモリは , ストレージに比べると普及は 遅いのですが , 128M バイトあたりが標準 になってきています。メモリ情報は , List 1- ⑧のように GlobalMemoryStatus API で取 得できます。 おわりに 今回利用した主な API を Table 2 にあげて おきます。今回は , ューザ環境を取得する プログラムを取り上げました。プロードバ ンドという言葉が花盛りです。 ADSL の普 及によって , メガ単位でのデータ転送が実 現してきました。しかし皮肉にも自身のパ ソコンが旧型すぎてその速さを感じること のできないユーザも多数います。ネットワ ークという分野は , 全体のバランスが整わ ないと , 思ったような効果が得られない分 野の代表例になるかもしれません。今回の 情報を活用して , ューザ側に立ったアプリ 成功時は 0 以外の値 ( T 日 UE ) , 失敗時は 0 (FALSE) ケーションを開発していきましよう。 Windows Programming Tips 1 2 /
マンドの互換性をとる場合でも簡単に対応 することができます。一般にこのような CD B の変換は , ATAPI または ASPI のドライバ 側で自動的に行われるので , さほど気にす ることはなく , ASPI を使用して SCSI と同じ コマンドを ATAPI デバイスに発行しても問 題なく動作します。 Windows での SCSI 制御 こまで , SCSI デバイスと ATAPI テパイ スについて基礎的な部分の解説を行ってき ました。この中で , SCSI と ATAPI の共通性 などが理解できたかと思います。 ここからは , 実際に Windows システム上 で SCSI デバイスを操作する方法について解 説していきたいと思います。 イ 6 C MAGAZINE 2001 11 このようなカードのことを ASPI ではアダブ ることを考慮して設計する必要があります。 ムを作成する場合 , 必ず複数のカードがあ ことができます。 ASPI を操作するプログラ 数の SCSI インタフェイスカードを実装する Windows に限らず , コンピュータには複 デバイスの検索 コマンドとその形式により分けられます。 P132Command API にセットするバケットの すが , それぞれの機能の呼び出しは SendAS けです。 ASPI にはいくつかの機能がありま SP132Command ( ) という API , たった 1 つだ 132. DLL という DLL に実装されている SendA ドバケットの送信に使用するものは WNASP 分操作することが可能です。実際のコマン 本的には Table 14 , 15 の 2 つの API だけで十 れぞれ使える API が決まっていますが , 基 ASPI にはいくつかバージョンがあり , そ n32 用のものについてだけ簡単に解説します。 ' こでは , Wi 仕様はあまり変わりません。 ありますが , 基本的な呼び出し関数 ( API ) の 用のほかに Win16 用と MS-DOS 用のものが Ad 叩 tec が定めたものです。 ASPI には rm32 制御するためのインタフェイスで , 前述の ASPI は Windows において SCSI デノヾイスを SCSI デバイスを制御する A 円「 AS 円」 TabIe 14 AS 曰 32 の主要な A 曰 機能 DLL 書式 引数 機能 DLL 書式 引数 返し値 返り値 AS 曰のサポート状況を確認する WNASP132. DLL DWORD cdecl_ ー GetASP132SupportInfo (void) : なし ビット 0 ~ 7 ビット 8 ~ 15 パソコンに装着されているホストアダブタの数 SS_COMP ( 0x01 ) のとき AS 曰が利用可能 SS FAILED 」 NIT ( 0xE4 ) のとき利用不可 AS 曰の機能を実行する WNASP132. DLL DWORD cdecl_ ー SendASP132Command ( LPSRB lpSRB ) : LPSRB lpSRBSRB (Servise Request Block ) へのポインタ SS_COMP ( 0X01 ) のとき正常にバラメータが受け渡される。それ以外の値はエラー TabIe 15 ASP ロマンドー覧 コマンド SC_HA QU 旧 Y SC GET_DEV_TYPE SC EXEC_SCSI_CMD SC ABORT SRB SC_RESET_DEV SC_GET_DISK 」 NFO 機能 0x01 ホストアダブタに接続されている SCSI デバイスの情報を取得する 0x00 ホストアダブタに関する情報を取得する 0x06 SCSI 接続のティスク情報を取得する (Windows NT 系不可 ) 0x04 指定の SCSI 機器をリセットする (Bus Device Reset メッセージを送る ) 0x03 実行中の SRB をアボートする 0x02 SCSI/ATAPI コマンドバケットの実行 SC_RESCAN SCSI BUS 0x07 SCSI) ( スを再スキャンする (Windows NT 系のみ ) タ (Adapter) と呼んでいます。 とくに Windows では ASPI は ATA インタフ ェイスも SCSI アダブタの一種として認識す るので , SCSI インタフェイスカードを挿す だけで , アダブタ数は 2 っとなります。つ まり , アダブタが複数ある環境はめずらし くありません。このようなアダブタの総数 や ASPI のサポート状況などの情報を取得す るのが GetASP132SupportInfo ( ) という API です。これを実行すると返り値のビット 0 ~ 7 にアダブタの数を返すので , この値が 1 以上のときのみアダブタの検索を行うよう にします (List 1 ) 。 実際にアダブタを検索し , その情報を取 得するには SC_HA_INQUIRY コマンドを使 用します。コマンドは , それぞれのコマン ドに対応する構造体変数を準備して , その バケットの中のコマンドコードに SC_HA_I NQUIRY を , SRB-HaId に対応するアダブ タ番号を設定します ( List2 ~ 5 , TabIe 16 ~ 20 ) 。このアダブタ番号は ASPI では SCSI イ ンタフェイスパス , または ATA インタフェ イスパスに 0 から順に振られている番号で , 番号の範囲は 0 ~ アダブタ数 -1 となります。 このような動作を指示する構造体は ASPI では基本的な構造はコマンド間で共通とな っており , SRB (Service Request BIock) と 呼ばれます。 SC HA_INQUIRY コマンドに 限らず ASPI を呼び出す場合には , この S アダブタの数を取得する / / 正常に終了したらアダブタ数を格納して脱出 if ( ( ( て引 t & 0 F00 ) ” 8 ) = = SS ー取 ) Adapters=rsIt & 0X00f 新 e lse t わて ow Exception()" t 1
P 『衄 m 加 List List 1 ユーザ環境を取得するサンプルプログラムの抜粋 ューザー環境の取得 #define STRICI' #include く航 ndows. い #include <windowsx. h> #include 土 nn しル #include く土 nsock. #include *. h> #include ” s p . h ” #include ”て esou て ce. ド BCK)L getnetworkdata(HWND hwnddlg); BmI.J socketinit(void); void getmem(HWND れ d 引 g void getdisk(YMNI) hwnddlg); ユーサー環境の取得 void getinfo(HWND hwnddlg) ch ー 92U3e て Name [ 256 DWORD ーー OSVERSIONINFO versionlnformation; 辷朝 % 辷日、 d す e 地畆ま目気 OSV, 0 0 羣いætver 取 ( & v s 土 0 れ I 社 or 盟 tio 島 ) ) い es ge 部 x 伍 wndd G ve お土 on 工ラ APPN 明 e , ーわ第一 ℃ 4S0 内 TER - みま ?OR 当ー WIN32 』ÜS : 阯 ( V s 土 0 社。 r 盟 0 れ・ d 等加幻之 = は S98 ) い 。は叩 y 信ら "windows つを い叩 Y ( 加 f i ow 日夕引 宅 e V 駅上 0 ー WIN32 ー訂訌 を地叩 y ( s uf ら "Windowg ~ 朝つい。い default: 、・ t て 0 ( 32 部 f 新 , Windows 第 ) 引 SendMessage(GetDIgItem(hwnddIg,IIX-. LIST1)'LB—ADDSTRING,O,(long)szBuff); wsprintf(szBuff,nversion %dAd E*0%n"'VersionInformation. 面粗ゴ0てVeてSi0n, versionlnformation. dwMinorversion , versionlnformation. szCSDVersion); wsprintf(szBuff,"Build *dün",VersionInformation. dwBuiIdNumber); SendMessage(GetDlgItem(hwnddl%IDC—L151),LB—ADDSTRING,0,(long)szBuff); wsprintf(szBuff," ユーサーネーム宅 s 基 0 基 n ” , szUs N 明 e SendMessage(ætDIgItem(hwnddIg,m:—LIST1),LB—ADDSTRING,0,(Iong)szBuff); socketinlt(); getnetworkdata(hwnddlg); getmem(hwnddlg); getdisk(hwnddlg); Diskchk void getdisk(HWND hwnddlg) CHAR szrPath[101; [ ル駅 GE ーⅡ - freebyte, total, セ Ota げて e char szVname[128J; DWORD gzVnameLen ま 12 DWORD nSN; *)RD MaxComponentLen; char szFsys[128]; DWORD szFsysLen 12 歸 0 bFile; 朝往 epy 信社ね新 6 : ituGetDåsFreespaceE*(szrpatbÜ &freebytej o&totaIfree))X を工 e セれ、 P 北 f ( szB f , 阨ドライプトータル GbYte" ( tO に引 . QuadPa て t / 1024 ) / ( 1024 * 1024 ) リ SendMessage(GetDlgItem(hwnddIg,Iæ-LIST1), LB—ADDSTRING,0,(long)szBuff); wsprintf(szBuff,"c ドライブ空容量 %d e ” ( to に a げ ree. QuadPa / 1024 ) / ( 1024 * 1024 ) SendMessage(ætDIgItem(hwnddlg'Iæ—LIST1)t LB—ADDSTRING,O, (long)szBuff); wsprintf(szBuff,"c ドライブ空容量記 b e % t0ta げて・ QuadP 矼 t SendMessage(GetDIgItem(hwnddIg,IIL 工・ I師1), I 追」 DD 望 RIN 0 , (Iong)szBuff); 三を臼 0 も tV 矼翻 6 て記土信ツ証 h ツ諞語加語い &nSN,&MaxComponentÄ,&bFiIe, を町 s なÉY en ) ) xeturn; wsprintf(szBuff,"Disk S/N ",nSN); SendMessage(ætDIgItem(hwnddIg,IDC—LIST1), ー ADDS 1 , 0 , (long)szBuffY; す。今回の例では , List1- ①のように , ま こ 1 年 管理を起動したものです。内容を見比べて ないパーツになります。しかし , ず dwPIatformId メンバの値から OS を大きく の新品の PC は , ほば標準で 128M ノヾイトは みましよう。 判別し , dwBuiIdNumber メンノヾから OS の 積んでいる状態です。ハードディスクと同 OS の判別 詳細の内容を取得しています。 じく , 実装量の差が大きい情報の 1 つでし まず OS の判別部分を見てみましよう。 バージョンとビルドナンバーの関係は よう。 こでは GetVersionEx API を利用して判別 TabIe 1 のようになっています。 / サンプルプログラム ューザ環境を取得する場合 , OS の判別 しています。その手順は , ① Ve 「 sio 可 nfo 「 mation 構造体の初期化 も必要ですが , 各ファイルのバージョン情 ② GetVersionEx A 日の実行 報などを取得する必要もあります。 OS が List1 は , サンプルプログラムの抜粋で ③ GetVersionEx A 日の返り値の評価 Windows 98 でも , comct132. d Ⅱなどのノヾー す。なお , ビルドには wsock32. lib , netapi ジョンによっては不具合が生じることもあ 32. lib のリンクが必要です。 となります。 GetVersionEx API は , Windo るのです。実際に利用する DLL などのチェ ws の現在のバージョンと OS 情報を構造体 今回作成したプログラムは , 起動すると Fig. 1 のように単純なダイアログボックス の各メンバに返すようになっています。 ックを怠らないようにしましよう。 を表示します。ーボタンを の情報を switch 文で分岐させます。 dwPlat ネットワーク環境の取得 クリックすると , 下のリストボックスにユ formld メンバには , Windows 3.1 / 95 / 98 / まず , List 1- ②のようにして , ユーザ名 ーザ環境の情報を表示します。 Fig. 2 は Wi NT などの情報が入り , dwBuiIdNumber メ nd0WS2000 に標準で備わっているシステム ンバには OS のビルド番号の情報が入りま を取得しています。 1 25 Windows Programming Tips
TabIe 31 Table 30 のバラメータの内容 プで使用できるようになっています。なお , バラメータ 内容 現在はきちんと規格として Format フィール TOC データ長 Fo 「 mat = 0001b のときは必ず OxOA となる ドが規定されていますが , これをサポート 開始確定セッション番号 確定している先頭セッション番号を示す しないドライプは比較的多いため , 基本的 最終確定セッション番号 確定している最終セッション番号を示す にこのべンダユニークパラメータを使用す TOC データを読み出したセクタのサブチャネ丿レ 0 に含まれる情報を示す ( Ta 団 e 26 る必要があります。 ADR 参照 ) 実際にセッションの情報を取得するとき トラックの属性情報を示す (TabIe 26 参照 ) コントロール には , このパラメータに対して , フォーマ 閉じられている ( 確定している ) セッションで , 最終セッション中の先頭トラック 最終確定セッションの 先頭トラック番号 番号 ット 01 , または 10 を設定した ReadTOC コ 最終確定セッションの マンドを使用することで , 指定したセッシ 最終確定セッションの先頭トラックのアドレスを取得する。 MSF ビットが 1 のと 先頭トラック開始アド きは MSF アドレスで , 0 のときは LBA で示される ョンのリードアウトトラックのアドレス ( サ レス プチャネル Q の Point が耙のときの値 ) がわ TabIe 32 ReadTOC 出力データ ( Fo 「 mat = 0010b ) かります。それを元に最初に取得したトラ 7 ック情報の補正を行って , 初めて正確にト (MSB) ラック情報を読めたことになるわけです。 オーディオデータの読み出しと保存 トラック情報を取り終えたら , 最後に実 際の読み出しを行います。これには , オー ディオデータなど CD 特有のデータを読み出 すためのコマンドである READ CD コマンド TNO (Table 33 , 34 ) を使用します。通常のデー Point タ読み出しでは , ハードディスクなどのダ MIN イレクトアクセスデバイスで使用される RE SEC AD コマンドで十分ですが , オーディオデー FRAME タやサプコーディングデータを読み出す場 0x00 合にはこれを使用しなければなりません。 PMIN このコマンドは , 比較的最近の SCSI 規格 PSEC で規定されたコマンドであるために , 古い PFRAME ドライプまでをサポートする場合には , 個 ※ TNO, Point, MIN, SEC, FRAME PSEC, PFRAME の意味は Fig. 10 を日召 PM , 別にドライプに合ったコマンドを使用する 必要があります。しかし , 今流通している TabIe 33 READ CD コマンド CD-ROM ドライプではほとんどでサポート 7 されているので , あまり問題となることは ないでしよう。とくに Windows 98 で READ CD コマンドのサポートが必須となる音楽 C D のデジタル再生機能が標準サポートされ たことで , まず対応していないドライプに お目にかかることはありません。 ただ , READ CD コマンドは多くの読み 出しモードを持ちますが , すべてをサポー トしているドライプはめったになく , とく にサプチャネル関係の読み出しはほとんど サポートされていません。 今回のようにオーディオトラック (CD- 58 C MAGAZINE 2001 11 0 3 TOC データ長 開始確定セッシ」ン番号 最終確定セッション番号 セッション番号 5 4 0 ィーっムっ 0 1 ・つムっ・ (C) ( 0 「 / 8 C) コントロー丿レ ADR 1 0 2 3 オペレーションコード ( 0xBE ) セクタタイプ 5 6 0 1 0 1 ーっ乙っ乙・広 0 ( 0 「 / 8 C) RESERVED RelAd 「 Rsved (MSB) 読み込み開始論理プロックアドレス (LSB) (MSB) 転送プロック長 EDC&ECC Use 「 Data (LSB) E 「「 0 「 Field Rsved サブチャネル選択ビット SYNC ヘッダコード Reserved 1 0 コントロールバイト
適切な位置に配置しなければなりません。 が必要な場合があります。 スのデバイスタイプ値が取得できたことに 現状は PCI バスが 32 ビットバスというこ このような情報は , 前出の SC-HA-INQU なります。 ともあり , 制限があっても 4 バイト単位 ( 32 IRY で取得される HA_Unique にあり , 実行 最初に呼び出した SC HA_INQUIRY の H ビット ) であることがほとんどです。この 時に使用するバッフアは必ずこれを見て , A_Count か , GetASP132SupportInfo ( ) で取 得したアダブタ数を元に , アダブタ番号を TabIe 18 List 3 , 4 の SRB_Flags で設定する値 (SC_EXEC—SCSI—CMDJ! ケットのときのみ有効 ) 0 ~ アダブタ数 -1 の間で設定して , それにつ 内容 値 ながるデノヾイスの検索を前述の手順ですべ ASP ロマンド実行終了検知にコールバック関数を使う SRB_POSTING 0x01 てのアダブタに対して行います ( Fig. 6 ) 。 転送経過モニタ機能を有効にする。この機能が使用できるかは , SC-HA— 爪 QU 旧 Y を実行したときに取得される HA ー Unique メンバのオフセット 2 に CDB の実行 表示されるので , それが ON のときのみ指定可能。これを ON にすると , SRB ー BufLen に転送データ残量が反映される ( 最終的に 0 になる ) 。このビットを CDB を SCSI や ATAPI 機器に送信して目的 ON にした場合 , 実行中に SRB の S 日 B BufLen メンバにデータ転送経過が 反映される の機能を実行させるには , SC_EXEC_SCSI CMD ファンクションを使用します。これ ターゲットからホストアダブタにデータを転送する場合に指定する SRB_D 旧」 N 0X08 を ASPI に対して送ることで , SCSI インタフ ホストアダブタからターゲットにテータを転送する場合に指定する SRB_D 旧 _OUT 0x10 ェイスカード , あるいは ATA インタフェイ ASP ロマンド実行終了検知にイベントカーネルオブジェクトを使用する SRB EVENT_NOTIFY 0X40 スは目的のデバイスにコマンドバケットを 送信して , 要求する動作を行わせます。 TabIe 19 List 3 , 4 の SRB_HaStat の値 呼び出しパラメータには , ・ SRB Hald, SRB_Target, SRB_Lun 正常終了 0x00 目的となるデバイスのアドレスを設定 トランザクション完了までの時間がとられたことを示す 0x09 ・ CDBByte 配列内 AS 曰実行中に S 日 B が破棄 , あるいはタイムアウトされたことを示す 0x0B 送信するコマンドバケット SCSIZ マンドの実行の際に Message Reject メッセージを受け取ったことを示す 0x0D ・ SRB CDBLen バスリセットが検出されたことを示す 0x0E コマンドバケットの長さ バリティエラーが検出されたことを示す 0x0F ・ SRB BufLen コマンド実行後に発行した日 equest Sense が失敗したことを示す 0X10 読み書きするデータのサイズ セレクションフェーズがタイムアウトしたことを示す 0X11 ・ SRB BufPointer データオーバラン , あるいはアンタ、一ランが発生したことを示す 0X12 そのデータへのポインタ 予期しないバスフリーフェーズが起こったことを示す 0x13 ・ SRB_Flags ターゲットのバスの使用状態の取得が失敗したことを示す 0X14 データの読み書き方向フラグ SRB D 旧 ※このステータスは実行がどのように終了したかを示すホストアダブタの情報 IN, または SRB D 旧 OUT ( 読み書き TabIe 20 List 3 , 4 の SRB_TargetStat の値 しないときは設定しない ) 値 ・ SRB SenseLen コマンドの実行が正常終了した 0X00 センス長を設定した SRB コマンドの実行が異常終了したことを示す 0x02 をそれぞれ引数として SendASP132Comman Search Data コマンドなどが指定された条件で正常終了した 0X04 d ( ) を呼び出します。 指定されたターゲット , あるいは論理ユ二ットが Busy 状態となっている 0X08 ・読み書きバッフアのアラインメント調整 コマンドリンクされたコマンドが正常に終了した 0X10 コマンドリンクの中で実行された Sea 「 ch Data コマンドなどが指定された条件によって正常終了 0X14 SCSI や ATA インタフェイスでは , DMA 転 した Reserve Unit などで予約されているデバイス , あるいはデバイスのテータ領域のアクセス禁止 送 (CPU を介さずにハードウェアによりデ 領域をアクセスしようとした ータを直接転送する手法 ) によりデータの ターゲットが Terminate I/O Process メッセージを受け取って I/O プロセスを終了したことを示 0x22 読み書きが行われることが一般的です。し す かし , DMA 転送ではハードウェアの制限に コマンドキューに空きがないことを示す 0x28 ※ SC コマンド実行後にステータスフェーズでターゲットが返すステータスパイトが入る。 SC 機器では意味がある より , 転送開始アドレスが 4 バイト単位の が , ATA 曰機器では意味のない値となるときがある。なお , ビット 0 , 6 , 7 は予約ビットなので , 必ずマスクして 0 と 位置になければならないなどの特定の条件 して扱わなければならない 48 C MAGAZINE 2001 11 SRB ENABLE RESIDUAL_COUNT 0X04 内容 内容 0x18
List 1 List 1 曾叩 r ( 加に e 地加 % 師及は衄 c 一バ処理 ・ iLB—ADD5?RING,0, い on の s 名別 ff わ ーーま虻 0 tSE - 新中 y ( & 洫 , ム 0 e れい > h ー ad , 4 塚 vsprintf(szBuff,"IP Addregs 薊 % in ーれに oa ( ) ) ” a 可 9 伍 40 回↓川ャを 0 return ー メモリ情報の取得 void getmem(ffÆND hwnddlg) DWORD dMem; MUORYSTANS 加 s に一 emse 阯 ' 記宿し元も口 新 s し朝 ng 比 = 。 sizeot ( い = 、を崋曇をミ 0 釧 p 斗 wsprintf( szBuff,(" トータルメモリ容量全 10d つ ! 碼し d “咽 ota ゆ hys / 1024 SendMessage(GetDIgItem(hwnddIg,IILLIST1),LB—ADIMRING,0,(long)snuff) 第 dMem mst.MotaIPhys ー mst.dwAvaiIPhys; wsprintf( szBuff ハ”利用中のメモリ物理容量 0d n し / 1024 、 ING,0,(long)szBuff) 引 * function: 盟 inD 地 proc ( ) LRESULT CALLBACK ー旧 inD 地 ( H , UINT message, WPARAM wparan, LPARAM 矼明 ) 、 HICON hlcon; LRESULT lResult ERROR—SUCCESS; switch (message) ( case WM—INITDIAI.m : hWndmain ー hlcon 第 LoadImage(hInst,MAKEIm.ESOURCE(IDI—ICON1)Y Ⅲ AGE ー ICON , 32 , 32 , 0 SendMessage(hDIg,WM-snICON,FALSE, (Iong)(HICON)hIcon); hlcon = LoadImage(hInst,MAKEINRESOURCE(IDI—ICON1), I 期 GE ー ICON 卩 2 , 32 , 0 SendMessage(hDIg,WM-SETICON,RUE,(Iong)(HmN)hIcon); return ( 迂 ( 矼 = SC-CLOSE) ( EndDialog ( , UE return TRUE; ) else return FALSE• イニシャライズ BØL socketinit(void) 前を。れ R 師」往 d ぬ駅 0 ( 第鬼 ) ても WSAS にに叩 ( VV 0 eq , return FALSE else ( ease W ー SYSCO : if (wversionRequested ! = wsaData. wVersion){ WSACIeanup(); return FALSE; return TRUE; break; case W ー CO D : if ( ま = 18 ー ON ) { getinfo(hDIg); return ( TRUE ( 矼 = IILCL ) ( *. 工IST1,IおーRES居ーC6姻屋姻,0,0しリ return ( 囲 ( 明 = I C 瓦 ) ( 一 i 引 og ( 垣 , TRUE return ( RUE Ne に wo て k データ取得 getnetworkdata(HWND hwnddlg) char szHname[256]; PHOS で望 hostent; IN-ADDR 土 引 0 ′ get 丘 6 は t 血 ( 、 2 月 wsprintf(szBuff,'Hostname 基れ % 号 2 日 name わ 辷山。 3 ャ 2 のい 次にソケットをイニシャライズし , 実際 に必要な情報にアクセスを行います。ソケ ットのイニシャライズは , List 1- ③のよう に WSAStartup API を使います。 今回取得するネットワークの情報は , ホ ストネームと IP アドレスです。ホストネー ムは , いわゆるコンピュータ名のことで , ほかの PC からの参照などにも利用されて います。ホストネームの取得は , ソケット をイニシャライズした後 , List 1- ④のよう に gethostname API を使います。 ホストネームが取得できれば , ListI- ⑤ のように , そのホストネームを利用して ( 引数にして ) データベースから gethostbyn ameAPI を使って IP アドレスを取得します。 このとき工ラーが返ってこなければ , 静的 に IP アドレスが割り振られていることにな 1 26 C MAGAZINE 2001 11 break; default: return FALSE ・ て e ヒ n ( 駅わ Fig. 2 Windows 2000 の「コンピュータの管理」ツール 一二コ 下ー示冖知」」 .- 气」はⅱー朝 名 M oso 負 W ) W32 て加 P 「研 s “凶 コンビュータの管理 ( ロー加・ バージョン 5021 S 等、・ P kl ビルド 21 早システムツール 製造元 M 鰤 0 負 C 。加 田 イベントとーア システム名 を システム情報 システム製造元 S ッ 0 研加 ッステムの概事 POG-OIVM-K(J) システムモテル 、ロハーめェアリゾ システム明重黷 ロポーネント 〉新一べース : をロソフトウェア プロセッサ xS Family5 を凵 S 叩 3 ー TMx ~ 釭 BDS 第トラョン en ⅸ 8 4.0 0 5 ロアプ丿ケーシ′ W 朝 1 あ ws ディレク C*WINNT を パフォーマンスロ災 ロケル 日本 共有フォルダ 物理メ刊の全容量 245216 KB デバイスマネージャ、 物理メ刊の空き容量 新 2 KB n ー物ル廾ーレ 仮想メ刊の全容量 7. 新 4 KB 工ゼュー管理 TabIe 1 バージョンとビルドナンバーの関係 バージョン dwMinorVersion dwBuildNumber 4.00.950 0 950 4.00.950A 0 950 4.00.950B 4.00.950C 4.10.1998 Win dows 95 の種類 Windows 95 Windows 95 十 Service Pack 1 OEM Service Release 1 OEM Service Release 2 OEM Service Release 2.1 OEM Service Release 2.5 Windows 98 1212 1998 0 0 1 0
CD - DA データの読み込み設定 / 実行例 (A) を読み出す場合のコマンドバラメータ の設定は , List 11 のようにセクタタイプを 000 の ALLTypes にセットして , UserData の ビットのみを立てます。そして , 読み出し を開始するアドレスを Read TOC コマンド で取得したデータを元に設定し , READ CD コマンドを発行します。そうして取得した データを , Windows ではマルチメディア I / 0 API などを使用して書き込んでいきます。 取得したデータは , Table35 のように 44100 Hz , 16 ビット , ステレオのリニア PCM フォ ーマットと同様の構造なので , マルチメデ TabIe 35 オーティオデータ出力形式 ( 1 フレームぶん ) ィア I / OAPI を使用して書き込むときには 7 6 5 データ変換などの作業をする必要性はあり ません。単に mmioWrite() を使ってそのま ま書き込むだけです。 さらに , このときに取得したデータを MP 3 に圧縮して書き込みたい場合には , CD か らオーディオデータを読み出す部分と , 圧 縮を行う部分についてスレッドを分割し , マルチスレッド動作を行うことで効率的な MP3 ファイルの生成を行うことができます このとき , READ CD コマンドの実行に はイベントカーネルオプジェクトを使うこ とで , 読み出し中の CPU 使用率を最低限に することが可能となります (Fig. 13 ) 。その ため , CD の読み出し速度よりも MP3 圧縮 が十分に速く , MP3 工ンコーダへの入力デ ータストリーム用の FIFO バッフアが十分に 大きければ , 読み出しと圧縮を同時に行う オンザフライエンコーディングが可能とな り , 高速な変換処理を行うことが可能です。 現在の一般的な MP3 ファイル作成ソフトで は , このようなオンザフライエンコーディ ングが一般的です。 ジッターコレクション オーディオデータの読み出しでは , 普通 のデータ読み出しと異なる現象が発生する ときがあります。それがジッター ( ふらっ き ) です。 オーディオデータの状態は , Fig. 9 のよ うにフレームごとに同期データがありませ ん。そもそもセクタという概念がオーディ オトラックのデータストリームには存在し 60 C MAGAZINE 2001 11 memset(&SRB,O,sizeof(SRB) 〃 SRB をゼロクリア SRB. SRB—Cmd=SC—EXEC—SCSI—CD; SRB. SRB—HaId=(BYTE)CDROMS[index] . adapter; SRB. SRB—Lun=(BYTE)CDROMS[indexl . ん SRB. SRB—Target=(BYTE)CDROMS[indexl . target; / / 読み込み指定 SRB. SRB—FIags=SRB—DIR—IN; SRB. SRB—SenseLen=SASE—LEN; / / 1 フレームぶんなので 2352 バイト SRB. SRB—BufLen=2352; SRB. SRB—BufPointer=(BYTE *)buf ・ SRB. SRB—CDBLen=12; SRB. CDBByte[Ol=SCSI—ReadCD; / / READ-CD コマンド * ( 0 *)&SRB. CDBBytet21=ReverseByte(loadingptr); / / 読み込み位置指定 / / 読み込みフレーム数指定 SRB. CDBByte[8]=1; 〃読み込み形式指定 (CD-DAI フレーム ) S . CDBBy ヒ e [ 9 ト 0X1 if (ExecuteSCSIComand(&SRB) 0 (LSB) 左チャンネルデータ ( 0 ) CO 0 ネ ャ チ 右」 CD 4 ーっ乙 (MSB) / っ f) 4- 左チャンネルデータ ( 1 ) ー、タ 、レ ネ ャ = CD 【 0 ( 0 2350 (LSB) 右チャンネルデータ ( 587 ) (MSB) 2351 Fig. 13 MP3 オンザフライエンコーティングのときのスレッドの動き データの読み出し データの読み出し 読み出し完了待ち C び日 OM からの 読み出し処理 △ △ ースレッドの動作の : 切り替わり MP3 圧縮処理 M データ圧縮処理アイドル時間
特集 2 自在に操る S Ⅷ日 る」という動作から見れば , SCSI と ATAPI 番号は 0 と 1 しか存在しないことになるなど では SCS ト 2 でのセンスデータ構造について にはほとんど差異がありません。 の規格上の違いはいくつかあります。 己述しています。 また , Windows では ATA ドライバは SCSI Table 9~13 に Request Sense というデバ ATAPI ではこの CDB の長さは 12 バイトと ドライバの一種として扱われ , SCSI デバイ イスの状態を取得するコマンドの SCSI と AT なっていますが , SCSI では 6 バイトと長さ スを操作するための ASPI はそのまま ATAPI API のそれぞれの CDB 形式とそのリザルト が違います。しかし , この ATAPI の余分に デバイスに対して操作を行うことができる 形式を示します。このコマンドは , コマン 長い 6 バイトはリザープ , つまり 0 となって ようになっています。冒頭で解説した抽象 ド実行後に Check Condition ステータスの発 います。また , コントロールバイトは通常 化が行われているため , SCSI デバイスと AT 生などで生成されたセンスデータを取得し SCSI では 0 に設定されるし , LUN には SCSI API デバイスはほとんど同じように操作す ます。報告するセンスデータがないときは , でも論理ユニットが 1 つだけであればそこ ることができます。ただし , ATAPI の場合 返されるセンスキーに NoSense を返します。 も 0 と設定されるので , 長さが違うだけで は 1 つの ATA バスに 2 つまでしかデバイスを 取得されるセンスデータは , SCSI-I/CCS/S 必要な設定に限れば , まったく同じコマン 接続できないので , 必然的にデバイスの ID CSI -2 で定義される構造が異なります。 ドになっているといえます。このため , コ TabIe 13 Request sense コマンドの詳細 ( バラメータの意味 ) バラメータ 一三ロ 内容 インフォメーションフィールドの値は有効なときに 1 この値には 0X70 か 0X71 が入る。 0X70 の場合は Check Condition ステータスが発生した後に Request Sense を行っ たとき。 0X71 の場合は Good ステータスを返して終了したコマンドのエラー情報を示す Copy コマンドや Compa 「 e コマンド , Copy and Compare コマンドを実行したときのみ有効で , 工ラーが発生したセ グメントデスクリプタを示す シーケンシャルアクセスデバイスで必須でサポートされる。ファイルマークが読まれたときに 1 シーケンシャルアクセスデバイスとプリンタテパイスのみ有効で , 記録メティアが終わったこと ( 紙なし , あるいはテ ープエンド ) であることを示す CDB で指定された転送長と指定されたテパイスの論理プロック長 ( セクタ長 ) が整合しないときに 1 センステータの発生したエラー要因を簡易的に示すコード ( キー ) 。さらに詳細理由がある場合には , ASC や ASCQ に 示される 代表的なセンスキーは次のとおり 名称 No Sense 0 Valid 工ラーコード セグメント番号 FileMark EOM 内容 とくに該当するセンスキーがないことを示す。正常に動作しているときに日 equest Se nse を行った場合 , あるいは FileMark, EOM, 旧のときに発生する 指定した論理ユニットが動作できない状態 CDB 上に不当なバラメータがあったときに主に検出される 指定された論理ユニットが書き込み禁止であるにもかかわらず書き込みを行おうとし 7 Data Protect たときに検出 インフォメーション 発生したエラーの詳細情報を示す (Valid ビットが 1 のとき ) オフセット 8 以降のセンスデータの長さを示す。この値は Request Sense コマンドで指定したアロケーション長フ 追加センスデータ長 ィールドの値とは無関係で , 実際のセンスデータの長さを取得することができる コマンド固有インフォメーション コマンド固有情報を示す 追加センスコード (ASC) センスキーの示す内容を補足するコード 追加センスコードクオリファイア ( ASCQ ) ASC で示された内容をさらに補足する センスデータで報告されたエラーを修復しなければならない場合のハードウェア部分を示す。これをサポートしない FRU ターゲットは常にここに 0X00 を入れる 後続のセンスキー固有インフォメーションが有効なときに 1 特定のセンスキーの値についての補足情報を示す センスキー Not Ready lllegal Request 2 5 SKSV センスキー固有インフォメーション 45 特集 2 自在に操る SCSI/ATAPI