ILockBytes
COM公式ドキュメント
ILockBytes インターフェースは、ディスクファイル、グローバルメモリ、データベースなどの物理ストレージによって裏付けられたバイト配列オブジェクトに実装されます。
メソッド 7
vtbl = vtable インデックス(0始まり)。HSP等からCOMメソッドをインデックス指定で呼ぶ際に使用します。0〜2 は IUnknown。
ReadAt メソッドは、バイト配列オブジェクトの先頭から指定されたオフセットの位置を起点として、指定されたバイト数を読み取ります。
| ulOffset | ULONGLONG | in | データを読み取る際の、バイト配列の先頭からの開始位置を指定します。 |
| pv | void* | out | バイト配列の読み取り先となるバッファへのポインター。このバッファのサイズは cb に格納されています。 |
| cb | DWORD | in | バイト配列から読み取ろうとするデータのバイト数を指定します。 |
| pcbRead | DWORD* | outoptional | バイト配列から実際に読み取られたバイト数を、このメソッドが書き込む ULONG へのポインター。この値が不要な場合は、このポインターに NULL を設定できます。その場合、このメソッドは実際に読み取られたバイト数を返しません。 |
戻り値
このメソッドは次のいずれかの値を返します。
| リターンコード | 説明 |
|---|---|
| S_OK | 指定されたバイト数が読み取られたか、バイト配列の末尾まで最大限のバイト数が読み取られたことを示します。 |
| E_FAIL | バイト配列からデータを読み取れませんでした。 |
| E_PENDING | 非同期ストレージのみ: 読み取り対象のデータの一部または全部が現在利用できません。 |
| STG_E_ACCESSDENIED | 呼び出し元にバイト配列へアクセスする権限がありません。 |
| STG_E_READFAULT | 読み取るべきバイト数と、実際に読み取られたバイト数が一致しません。 |
解説(Remarks)
ILockBytes::ReadAt は、バイト配列オブジェクトからバイトを読み取ります。実際に読み取られたバイト数を報告します。読み取り中にエラーが発生した場合や、バイト配列の末尾に達した場合、この値は要求したバイト数より少なくなることがあります。
操作がバイト配列の末尾に達したために、指定されたバイト数より少なく読み取ることになってもエラーではありません。これは、MS-DOS のファイルアロケーションテーブル (FAT) ファイルシステムのファイルに見られるのと同じ end-of-file の動作である点に注意してください。
WriteAt メソッドは、バイト配列の先頭から指定されたオフセットの位置を起点として、指定されたバイト数を書き込みます。
| ulOffset | ULONGLONG | in | 書き込むデータの、バイト配列の先頭からの開始位置を指定します。 |
| pv | void* | in | 書き込むデータを格納しているバッファへのポインター。 |
| cb | DWORD | in | バイト配列に書き込もうとするデータのバイト数を指定します。 |
| pcbWritten | DWORD* | outoptional | バイト配列に実際に書き込まれたバイト数を、このメソッドが設定する場所へのポインター。この値が不要な場合は、このポインターに NULL を設定できます。その場合、このメソッドは実際に書き込まれたバイト数を返しません。 |
戻り値
このメソッドは次のいずれかの値を返します。
| リターンコード | 説明 |
|---|---|
| S_OK | 指定されたバイト数が書き込まれたことを示します。 |
| E_FAIL | 書き込み操作中に一般的な失敗が発生しました。 |
| E_PENDING | 非同期ストレージのみ: 書き込み対象のデータの一部または全部が現在利用できません。 |
| STG_E_ACCESSDENIED | 呼び出し元に、このバイト配列を書き込むための十分な権限がありません。 |
| STG_E_WRITEFAULT | 書き込むべきバイト数と、実際に書き込まれたバイト数が一致しません。 |
| STG_E_MEDIUMFULL | ストレージデバイスに空き領域がないため、書き込み操作が完了しませんでした。実際に書き込まれたバイト数は pcbWritten に返されます。 |
解説(Remarks)
ILockBytes::WriteAt は、バイト配列内の指定された位置に、指定されたデータを書き込みます。エラーが返される場合でも、実際に書き込まれたバイト数は常に pcbWritten に返さなければなりません。バイト数がゼロの場合、書き込み操作は何も行いません。
ulOffset がバイト配列の末尾を超えており、かつ cb がゼロより大きい場合、ILockBytes::WriteAt はバイト配列のサイズを拡大します。バイト配列に書き込まれる埋め込みバイトは、特定の値には初期化されません。
Flush メソッドは、ILockBytes の実装が保持している内部バッファが、基盤となる物理ストレージに確実に書き出されるようにします。
戻り値
このメソッドは次のいずれかの値を返します。
| リターンコード | 説明 |
|---|---|
| S_OK | フラッシュ操作は成功しました。 |
| STG_E_ACCESSDENIED | 呼び出し元にバイト配列へアクセスする権限がありません。 |
| STG_E_MEDIUMFULL | ストレージデバイスに空き領域がないため、フラッシュ操作が完了しません。 |
| E_FAIL | データ書き込み中の一般的な失敗です。 |
| STG_E_TOOMANYFILESOPEN | 特定の状況下では、Flush メソッドはダウンロードして閉じることによるフラッシュを実行するため、利用可能なファイルハンドルがない場合に STG_E_TOOMANYFILESOPEN が返されることがあります。 |
| STG_E_INVALIDHANDLE | 基盤となるファイルが早期に閉じられたか、正しいフロッピーディスクが無効なものに交換されました。 |
解説(Remarks)
ILockBytes::Flush は、内部バッファを基盤となるストレージデバイスにフラッシュします。
COM が提供する複合ファイルの実装は、データの損失を防ぐ 2 フェーズコミットプロセスを実現するために、トランザクションコミット操作中にこのメソッドを呼び出します。
SetSize メソッドは、バイト配列のサイズを変更します。
| cb | ULONGLONG | in | バイト配列の新しいサイズをバイト数で指定します。 |
戻り値
このメソッドは次のいずれかの値を返します。
| リターンコード | 説明 |
|---|---|
| S_OK | バイト配列のサイズが正常に変更されました。 |
| STG_E_ACCESSDENIED | 呼び出し元にバイト配列へアクセスする権限がありません。 |
| STG_E_MEDIUMFULL | ストレージデバイスに空き領域がないため、バイト配列のサイズは変更されません。 |
解説(Remarks)
ILockBytes::SetSize は、バイト配列のサイズを変更します。cb パラメーターが現在のバイト配列より大きい場合、バイト配列は指定されたサイズまで拡張され、その間の領域は未定義の値のバイトで埋められます。これは、シークポインターが現在のストリーム末尾を超えている場合の ILockBytes::WriteAt と同じ動作です。
cb パラメーターが現在のバイト配列より小さい場合、バイト配列は指定されたサイズに切り詰められます。
呼び出し元への注意
オペレーティングシステムやネットワークでのキャッシュバッファリングのため、呼び出し元は STG_E_MEDIUMFULL が適切なタイミングで返されることを当てにできません。ただし、一部の ILockBytes 実装はこれをサポートする可能性があるため、呼び出し元はこのリターンコードを処理できなければなりません。LockRegion メソッドは、バイト配列内の指定されたバイト範囲へのアクセスを制限します。
| libOffset | ULONGLONG | in | 範囲の先頭のバイトオフセットを指定します。 |
| cb | ULONGLONG | in | 制限する範囲の長さをバイト単位で指定します。 |
| dwLockType | DWORD | in | 範囲へのアクセスに対して要求する制限の種類を指定します。このパラメーターは LOCKTYPE 列挙体の値のいずれかを使用します。 |
戻り値
このメソッドは次のいずれかの値を返します。
| リターンコード | 説明 |
|---|---|
| S_OK | 指定されたバイト範囲がロックされました。 |
| STG_E_INVALIDFUNCTION | ロックがまったくサポートされていないか、要求された特定の種類のロックがサポートされていません。 |
| STG_E_ACCESSDENIED | 呼び出し元の権限が不十分であるか、別の呼び出し元がファイルを開いてロックしているため、アクセスが拒否されました。 |
| STG_E_LOCKVIOLATION | 別の呼び出し元がファイルを開いてロックしているため、アクセスが拒否されました。 |
| STG_E_INVALIDHANDLE | 基盤となるファイルが早期に閉じられたか、正しいフロッピーディスクが無効なものに交換されました。 |
解説(Remarks)
ILockBytes::LockRegion は、指定されたバイト範囲へのアクセスを制限します。ある領域がロックされると、他者がその制限範囲へアクセスしようとする試みは、STG_E_ACCESSDENIED エラーで失敗しなければなりません。
バイト範囲は、現在のバイト配列の末尾を超えて延長できます。配列の末尾を超えてロックすることは、実際にはバイト配列の一部であるデータを変更することなく、バイト配列オブジェクトの異なるインスタンス間で通信する手段として役立ちます。たとえば、複合ファイル用の ILockBytes 実装は、現在付与されている権限を示すために特定のロック領域を使用して、配列の現在の末尾を超えたロックをアクセス制御の手段として利用することができます。
dwLockType パラメーターは、 LOCKTYPE 列挙体の値を使用して、3 種類のロックのいずれかを指定します。種類は次のとおりです。他の書き込み側を排除するロック、他の読み取り側または書き込み側を排除するロック、そして指定された範囲に対して 1 つの要求元だけがロックを取得できるロックです。この 3 番目の種類のロックは通常、他の 2 つのロック種類のいずれかのエイリアスであり、実装者が他の動作を追加することも許容します。あるバイト配列は、最初の 2 つの種類のいずれか、または両方をサポートする場合があります。
特定の ILockBytes 実装がサポートするロック種類を判別するには、 ILockBytes::Stat の呼び出しによって返される STATSTG 構造体の grfLocksSupported メンバーを調べます。
ILockBytes::LockRegion でロックした領域は、後で libOffset、cb、dwLockType の各パラメーターにまったく同じ値を指定して ILockBytes::UnlockRegion を呼び出し、明示的にロック解除しなければなりません。ストリームを解放する前に、領域をロック解除する必要があります。隣接する 2 つの領域を個別にロックしてから、1 回のロック解除呼び出しでまとめて解除することはできません。
呼び出し元への注意
サポートされるロックの種類は任意であり、 ILockBytes の実装ごとに異なる可能性があるため、STG_E_INVALIDFUNCTION エラーを処理するコードを用意しなければなりません。実装者への注意
このメソッドのサポートは、 ILockBytes 実装の上に構築されるストレージオブジェクトがどのように使用されるかによって異なります。バイト配列の基盤となるストレージデバイス上で、任意の時点で 1 つのストレージオブジェクトしか開けないことがわかっている場合、 ILockBytes 実装はロックをサポートする必要はありません。ただし、ストレージオブジェクトを同時に複数開くことが可能な場合は、それらを調整するために領域ロックが必要です。LockRegion の実装は、すべてのロック種類、一部のロック種類、またはまったくロック種類をサポートしないことを選択できます。サポートされていないロック種類については、実装は STG_E_INVALIDFUNCTION を返すべきです。
UnlockRegion メソッドは、以前にロックされたバイト範囲に対するアクセス制限を解除します。
| libOffset | ULONGLONG | in | 範囲の先頭のバイトオフセットを指定します。 |
| cb | ULONGLONG | in | 制限されている範囲の長さをバイト単位で指定します。 |
| dwLockType | DWORD | in | 以前にその範囲へ設定したアクセス制限の種類を指定します。このパラメーターは LOCKTYPE 列挙体の値を使用します。 |
戻り値
このメソッドは次のいずれかの値を返します。
| リターンコード | 説明 |
|---|---|
| S_OK | バイト範囲のロックが解除されました。 |
| STG_E_INVALIDFUNCTION | ロックがまったくサポートされていないか、要求された特定の種類のロックがサポートされていません。 |
| STG_E_LOCKVIOLATION | 要求されたロック解除を許可できません。 |
解説(Remarks)
ILockBytes::UnlockRegion は、 ILockBytes::LockRegion の呼び出しによって以前にロックした領域のロックを解除します。ロックした各領域は、対応する ILockBytes::LockRegion の呼び出しと同じ libOffset、cb、dwLockType の各パラメーター値を使用して、明示的にロック解除しなければなりません。隣接する 2 つの領域を個別にロックしてから、1 回のロック解除呼び出しでまとめて解除することはできません。
Stat メソッドは、このバイト配列オブジェクトに関する情報を格納した STATSTG 構造体を取得します。
| pstatstg | STATSTG* | out | このメソッドがこのバイト配列オブジェクトに関する情報を格納する STATSTG 構造体へのポインター。エラーが発生した場合、ポインターは NULL になります。 |
| grfStatFlag | DWORD | in | このメソッドが STATSTG 構造体の pwcsName メンバーを提供するかどうかを、 STATFLAG 列挙体から取得した値で指定します。STATFLAG_NONAME が指定された場合、 STATSTG の pwcsName メンバーは提供されず、メモリ割り当て操作が節約されます。もう一方の値である STATFLAG_DEFAULT は、 STATSTG 構造体のすべてのメンバーを提供することを示します。 |
戻り値
このメソッドは次のいずれかの値を返します。
| リターンコード | 説明 |
|---|---|
| S_OK | STATSTG 構造体が指定された場所に正常に返されました。 |
| E_OUTOFMEMORY | 構造体内の name メンバー用のメモリが不足していたため、STATSTG 構造体は返されませんでした。 |
| STG_E_ACCESSDENIED | 呼び出し元がバイト配列へのアクセス権を持っていなかったため、STATSTG 構造体は返されませんでした。 |
| STG_E_INSUFFICIENTMEMORY | メモリが不足していたため、STATSTG 構造体は返されませんでした。 |
| STG_E_INVALIDFLAG | grfStateFlag パラメーターの値が有効ではありません。 |
| STG_E_INVALIDPOINTER | pStatStg パラメーターの値が有効ではありません。 |
解説(Remarks)
ILockBytes::Stat は、バイト配列オブジェクトに関する情報を STATSTG 構造体で提供します。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
HSP用 COM定義
#usecom / #comfunc によるHSPのCOM呼び出し定義。数字は vtbl インデックス(0始まり)。クラスIDが無い場合 #usecom の末尾は "{}"、ある場合は "{CLSID}"。
#define global IID_ILockBytes "{0000000A-0000-0000-C000-000000000046}" #usecom global ILockBytes IID_ILockBytes "{}" #comfunc global ILockBytes_ReadAt 3 int64,sptr,int,var #comfunc global ILockBytes_WriteAt 4 int64,sptr,int,var #comfunc global ILockBytes_Flush 5 #comfunc global ILockBytes_SetSize 6 int64 #comfunc global ILockBytes_LockRegion 7 int64,int64,int #comfunc global ILockBytes_UnlockRegion 8 int64,int64,int #comfunc global ILockBytes_Stat 9 var,int ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数は var(変数直渡し)。varptr 方式にも切替可。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。#define global IID_ILockBytes "{0000000A-0000-0000-C000-000000000046}" #usecom global ILockBytes IID_ILockBytes "{}" #comfunc global ILockBytes_ReadAt 3 int64,sptr,int,sptr #comfunc global ILockBytes_WriteAt 4 int64,sptr,int,sptr #comfunc global ILockBytes_Flush 5 #comfunc global ILockBytes_SetSize 6 int64 #comfunc global ILockBytes_LockRegion 7 int64,int64,int #comfunc global ILockBytes_UnlockRegion 8 int64,int64,int #comfunc global ILockBytes_Stat 9 sptr,int ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数はポインタ方式(token=sptr / 呼び出しは varptr(変数))。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。