Функция 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 . Дескриптор памяти и его содержимое не нарушаются при создании нового объекта массива байтов.
Начальный размер массива байтов — это размер hGlobal , возвращаемый функцией GlobalSize . Это не обязательно тот же размер, который был изначально выделен для дескриптора из-за округления. Если важен логический размер массива байтов, выполните вызов 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, но это использование не рекомендуется. HGLOBALs, выделенные с помощью GMEM_FIXED , на самом деле не являются дескрипторами, и их значение может измениться при перераспределении. Если дескриптор памяти был выделен с помощью GMEM_FIXED а fDeleteOnRelease имеет значение FALSE, то вызывающий объект должен вызвать Метод GetHGlobalFromILockBytes , чтобы получить правильное значение HGLOBAL, чтобы освободить дескриптор.
Эта реализация ILockBytes не поддерживает блокировку регионов. Приложения, использующие эту реализацию с функциями StgCreateDocfileOnILockBytes или StgOpenStorageOnILockBytes , не должны открывать несколько параллельных экземпляров в одном объекте ILockBytes .
До Windows 7 и Windows Server 2008 R2 эта реализация не обнуляла память при вызове GlobalReAlloc для увеличения блока памяти. Увеличение размера массива байтов с помощью ILockBytes::SetSize или путем записи в расположение после текущего конца массива байтов приведет к тому, что все незаписанные части вновь выделенной памяти останутся неинициализированными. Объекты хранилища, возвращаемые stgCreateDocfileOnILockBytes и StgOpenStorageOnILockBytes , могут увеличить размер массива байтов без инициализации всего вновь выделенного пространства.
Составные файлы в памяти обычно используются как временное пространство или с ИНТЕРФЕЙСами API, для которых требуется объект хранилища, и в этих случаях неинициализированная память, как правило, не вызывает проблем. Однако если содержимое блока памяти будет записано в файл, рассмотрите следующие варианты, чтобы избежать потенциального раскрытия информации:
- Скопируйте логическое содержимое составного файла в памяти в целевой файл с помощью метода IStorage::CopyTo , а не непосредственной записи содержимого блока памяти.
- Вместо составного файла в памяти создайте временный файл, вызвав StgCreateStorageEx со значением NULL для параметра pwcsName . Когда нужно выполнить запись в целевой файл, используйте метод IRootStorage::SwitchToFile .
- Реализуйте интерфейс ILockBytes таким образом, чтобы перераспределение памяти обнулялось (см., например, флаг HEAP_ZERO_MEMORY в HeapReAlloc). Затем содержимое памяти этого массива байтов можно записать в файл.
Требования
Требование | Значение |
---|---|
Минимальная версия клиента | Windows 2000 Профессиональная [классические приложения | Приложения UWP] |
Минимальная версия сервера | Windows 2000 Server [классические приложения | Приложения UWP] |
Целевая платформа | Windows |
Header | coml2api.h (включая Ole2.h) |
Библиотека | Ole32.lib |
DLL | Ole32.dll |