CreateILockBytesOnHGlobal 函数 (coml2api.h)
CreateILockBytesOnHGlobal 函数创建一个字节数组对象,该对象使用 HGLOBAL 内存句柄来存储用于复合文件的内存中存储的字节。 此对象是 ILockBytes 接口的 OLE 提供的实现。
返回的字节数组对象支持读取和写入,但不支持区域锁定 。 对象调用 GlobalReAlloc 函数以根据需要增加内存块。
语法
HRESULT CreateILockBytesOnHGlobal(
[in] HGLOBAL hGlobal,
[in] BOOL fDeleteOnRelease,
[out] LPLOCKBYTES *pplkbyt
);
参数
[in] hGlobal
由 GlobalAlloc 函数分配的内存句柄,如果为 NULL,则改为分配新句柄。 必须将句柄分配为可移动和不可存储。
[in] fDeleteOnRelease
一个标志,指定释放对象时是否应自动释放此字节数组对象的基础句柄。 如果设置为 FALSE,则调用方必须在最终发布后释放 hGlobal 。 如果设置为 TRUE,则最终版本将自动释放 hGlobal 参数。
[out] pplkbyt
接收指向新字节数组对象的接口指针的 ILockBytes 指针变量的地址。
返回值
此函数支持标准返回值 E_INVALIDARG 和 E_OUTOFMEMORY,以及以下值:
注解
如果 hGlobal 为 NULL, 则 CreateILockBytesOnHGlobal 会分配一个新的内存句柄,并且字节数组最初为空。
如果 hGlobal 不为 NULL,则字节数组对象的初始内容是内存块的当前内容。 因此,此函数可用于打开内存中的现有字节数组,例如重新加载以前由 StgCreateDocfileOnILockBytes 函数创建的存储对象。 内存句柄及其内容不受创建新字节数组对象的干扰。
字节数组的初始大小是 GlobalSize 函数返回的 hGlobal 大小。 这不一定与由于舍入而最初为句柄分配的大小相同。 如果字节数组的逻辑大小很重要,请按照调用 CreateILockBytesOnHGlobal 并调用 ILockBytes::SetSize。
使用 CreateStreamOnHGlobal 创建字节数组对象后, StgCreateDocfileOnILockBytes 可用于在内存中创建新的存储对象,或者 StgOpenStorageOnILockBytes 可用于重新打开内存块中已包含的以前存在的存储对象。 可以调用 GetHGlobalFromILockBytes 来检索与字节数组对象关联的内存句柄。
如果将内存句柄传递给 CreateILockBytesOnHGlobal ,或者调用 GetHGlobalFromILockBytes ,则调用方可以直接访问此函数的内存句柄,而字节数组对象仍在使用该函数。 在使用此功能及其影响时,应适当谨慎:
- 请勿在字节数组对象的生存期内释放 hGlobal 内存句柄。 在释放内存句柄之前,必须调用 ILockBytes::Release。
- 请勿在字节数组对象的生存期内调用 GlobalReAlloc 来更改内存句柄的大小。 这可能会导致应用程序崩溃或内存损坏。 避免在同一内存句柄上创建多个字节数组对象,因为 ILockBytes::WriteAt 和 ILockBytes::SetSize 方法可能在内部调用 GlobalReAlloc。
- 如果可能,请避免在字节数组对象的生存期内访问内存块,因为该对象可能在内部调用 GlobalReAlloc ,并且不会对其大小和位置做出假设。 如果必须访问内存块,则内存访问调用应围绕对 GlobalLock 和 GlobalUnLock 的调用。
- 避免在使用 GlobalLock 锁定内存句柄时调用 对象的 方法。 这可能会导致方法调用不可预测的失败。
HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE,iSize);
if (!hMem)
AfxThrowMemoryException();
LPVOID pCompoundFile = ::GlobalLock(hMem);
... // Fill memory
::GlobalUnlock(hMem);
CComPtr<ILockBytes> spLockBytes;
HRESULT hr = ::CreateILockBytesOnHGlobal(hMem,FALSE,&spLockBytes);
CreateILockBytesOnHGlobal 将接受 使用 GMEM_FIXED 分配的内存,但不建议使用此用法。 使用 GMEM_FIXED 分配的 HGLOBALs 不是真正的句柄,其值在重新分配时可能会更改。 如果使用 GMEM_FIXED 分配内存句柄,并且 fDeleteOnRelease 为 FALSE,则调用方必须调用 GetHGlobalFromILockBytes 以获取正确的 HGLOBAL 值才能释放句柄。
ILockBytes 的此实现不支持区域锁定。 将此实现与 StgCreateDocfileOnILockBytes 或 StgOpenStorageOnILockBytes 函数配合使用的应用程序应避免在同一 ILockBytes 对象上打开多个并发实例。
在 Windows 7 和 Windows Server 2008 R2 之前,此实现在调用 GlobalReAlloc 以增加内存块时不会为零内存。 使用 ILockBytes::SetSize 增加字节数组的大小,或者通过写入字节数组当前末尾后的位置来增加字节数组的大小,将使新分配的内存的任何未写入部分未初始化。 StgCreateDocfileOnILockBytes 和 StgOpenStorageOnILockBytes 返回的存储对象可能会增加字节数组的大小,而无需初始化所有新分配的空间。
内存中的复合文件通常用作暂存空间或与需要存储对象的 API 一起使用,在这些情况下,未初始化的内存通常不是问题。 但是,如果将内存块的内容写入文件,请考虑以下替代方法以避免潜在的信息泄露:
- 使用 IStorage::CopyTo 方法将内存中复合文件的逻辑内容复制到目标文件,而不是直接写入内存块的内容。
- 通过使用 pwcsName 参数的 NULL 值调用 StgCreateStorageEx 来创建临时文件,而不是内存中的复合文件。 当需要写入目标文件时,请使用 IRootStorage::SwitchToFile 方法。
- 实现 ILockBytes 接口,使内存重新分配归零 (例如 HeapReAlloc) 中的HEAP_ZERO_MEMORY标志。 然后,可以将此字节数组的内存内容写入文件。
要求
要求 | 值 |
---|---|
最低受支持的客户端 | Windows 2000 专业版 [桌面应用 |UWP 应用] |
最低受支持的服务器 | Windows 2000 Server [桌面应用 |UWP 应用] |
目标平台 | Windows |
标头 | coml2api.h (包括 Ole2.h) |
Library | Ole32.lib |
DLL | Ole32.dll |