CreateStreamOnHGlobal 関数 (combaseapi.h)
CreateStreamOnHGlobal 関数は、HGLOBAL メモリ ハンドルを使用してストリームの内容を格納するストリーム オブジェクトを作成します。 このオブジェクトは、 IStream インターフェイスの OLE で提供される実装です。
返されるストリーム オブジェクトは、読み取りと書き込みの両方をサポートし、トランザクションを行わず、リージョンロックをサポートしていません。 オブジェクトは GlobalReAlloc 関数を呼び出して、必要に応じてメモリ ブロックを拡張します。
構文
HRESULT CreateStreamOnHGlobal(
[in] HGLOBAL hGlobal,
[in] BOOL fDeleteOnRelease,
[out] LPSTREAM *ppstm
);
パラメーター
[in] hGlobal
GlobalAlloc 関数によって割り当てられたメモリ ハンドル。NULL の場合は、代わりに新しいハンドルが割り当てられます。 ハンドルは、移動可能および非カード可能として割り当てる必要があります。
[in] fDeleteOnRelease
ストリーム オブジェクトが解放されたときに、このストリーム オブジェクトの基になるハンドルを自動的に解放するかどうかを示す 値。 FALSE に設定されている場合、呼び出し元は最終リリース後に hGlobal を解放する必要があります。 TRUE に設定すると、最終的なリリースによって基になるハンドルが自動的に解放されます。 fDeleteOnRelease が FALSE の場合の詳細については、「解説」を参照してください。
[out] ppstm
新しいストリーム オブジェクトへのインターフェイス ポインターを受け取る IStream* ポインター変数のアドレス。 その値を NULL にすることはできません。
戻り値
この関数は、標準の戻り値E_INVALIDARGとE_OUTOFMEMORY、および次の値をサポートします。
解説
hGlobal が NULL の場合、関数は新しいメモリ ハンドルを割り当て、ストリームは最初は空です。
hGlobal が NULL でない場合、ストリームの初期コンテンツはメモリ ブロックの現在の内容になります。 したがって、 CreateStreamOnHGlobal を使用して、メモリ内の既存のストリームを開くことができます。 メモリ ハンドルとその内容は、新しいストリーム オブジェクトの作成によって妨げされません。
ストリームの初期サイズは、GlobalSize 関数によって返される hGlobal のサイズです。 丸めのため、これはハンドルに最初に割り当てられたサイズと必ずしも同じではありません。 ストリームの論理サイズが重要な場合は、この関数の呼び出しに従って IStream::SetSize メソッドを呼び出します。
新しいストリーム オブジェクトの最初のシーク位置は、ストリームの先頭です。
CreateStreamOnHGlobal を使用してストリーム オブジェクトを作成した後、GetHGlobalFromStream を呼び出して、ストリーム オブジェクトに関連付けられているメモリ ハンドルを取得します。
メモリ ハンドルが CreateStreamOnHGlobal に渡される場合、または GetHGlobalFromStream が呼び出された場合、この関数のメモリ ハンドルは、ストリーム オブジェクトによって引き続き使用されている間、呼び出し元から直接アクセスできます。 この機能とその影響を使用する場合は、適切な注意が必要です。
- ストリーム オブジェクトの有効期間中は 、hGlobal メモリ ハンドルを解放しないでください。 メモリ ハンドルを解放する前に、IStream::Release を呼び出す必要があります。
- GlobalReAlloc を呼び出して、ストリーム オブジェクトまたはその複製の有効期間中にメモリ ハンドルのサイズを変更しないでください。 これにより、アプリケーションのクラッシュやメモリの破損が発生する可能性があります。 IStream::Write メソッドと IStream::SetSize メソッドは GlobalReAlloc を内部的に呼び出す可能性があるため、同じメモリ ハンドルで複数のストリーム オブジェクトを個別に作成することは避けてください。 IStream::Clone メソッドを使用すると、元のストリーム オブジェクトとのアクセスを適切に調整するのと同じメモリ ハンドルに基づいて新しいストリーム オブジェクトを作成できます。
- 可能であれば、ストリーム オブジェクトの有効期間中にメモリ ブロックにアクセスしないようにします。これは、オブジェクトが内部的に GlobalReAlloc を呼び出し、そのサイズと場所に関する仮定を行わない可能性があるためです。 メモリ ブロックにアクセスする必要がある場合は、メモリ アクセス呼び出しを GlobalLock と GlobalUnLock の呼び出しで囲む必要があります。
- GlobalLock でメモリ ハンドルがロックされている間は、オブジェクトのメソッドを呼び出さないようにします。 これにより、メソッド呼び出しが予期しない失敗する可能性があります。
hGlobal パラメーターとして渡されるメモリ ハンドルは、次の例に示すように、移動可能で非カード可能として割り当てる必要があります。
HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE,iSize);
if (!hMem)
AfxThrowMemoryException();
LPVOID pImage = ::GlobalLock(hMem);
... // Fill memory
::GlobalUnlock(hMem);
CComPtr<IStream> spStream;
HRESULT hr = ::CreateStreamOnHGlobal(hMem,FALSE,&spStream);
CreateStreamOnHGlobal は 、GMEM_FIXEDで割り当てられたメモリ ハンドルを受け入れますが、この使用は推奨されません。 GMEM_FIXEDで割り当てられた HGLOBAL は実際には処理されず、再割り当て時に値が変更される可能性があります。 メモリ ハンドルが GMEM_FIXED で割り当てられ、fDeleteOnRelease が FALSE の場合、呼び出し元は GetHGlobalFromStream を呼び出して、解放するために正しいハンドルを取得する必要があります。
Windows 7 および Windows Server 2008 R2 より前では、 GlobalReAlloc を呼び出してメモリ ブロックを拡張するときに、この実装ではメモリがゼロになりませんでした。 IStream::SetSize を使用してストリームのサイズを大きくするか、ストリームの現在の末尾を超える場所に書き込むことで、新しく割り当てられたメモリの一部が初期化されていない可能性があります。
要件
サポートされている最小のクライアント | Windows 2000 Professional [デスクトップ アプリ |UWP アプリ] |
サポートされている最小のサーバー | Windows 2000 Server [デスクトップ アプリ |UWP アプリ] |
対象プラットフォーム | Windows |
ヘッダー | combaseapi.h |
Library | Ole32.lib |
[DLL] | Ole32.dll |