Compartilhar via


Armazenamento estruturado no MAPI

Aplica-se a: Outlook 2013 | Outlook 2016

O armazenamento estruturado refere-se à organização hierárquica de armazenamento introduzida com COM. Em um ambiente de armazenamento estruturado, o armazenamento é organizado em dois ou três tipos de objetos:

  • Stream objetos

  • Bloquear objetos bytes

  • Objetos de armazenamento

Stream e os bytes de bloqueio são objetos de nível inferior que acessam diretamente os dados. Stream objetos implementam a interface IStream que define métodos para leitura, gravação, posicionamento e cópia de bytes de dados. Os objetos Bytes de bloqueio implementam outra interface COM, ILockBytes, para acessar dados com uma matriz de bytes. As matrizes de bytes normalmente são usadas para fornecer acesso personalizado ao armazenamento subjacente.

Os objetos de armazenamento são colocados em camadas na parte superior dos objetos de bytes de fluxo ou de bloqueio; eles podem conter um ou mais desses objetos, bem como outros objetos de armazenamento. Os objetos de armazenamento implementam a interface IStorage que define métodos para criar, acessar e manter objetos aninhados.

Como IStream, ILockBytes e IStorage são interfaces COM em vez de interfaces MAPI, seus métodos retornam valores de erro COM em vez de valores MAPI. Clientes e provedores de serviços que chamam métodos nessas interfaces devem usar a função de API MapStorageSCode para traduzir esses valores em valores de erro MAPI. Para obter mais informações, consulte MapStorageSCode.

Clientes e provedores de serviços usam armazenamento estruturado para trabalhar com propriedades muito grandes para manter com os métodos IMAPIProp , normalmente grandes propriedades binárias e cadeia de caracteres grandes. Uma das maneiras comuns de clientes ou provedores de serviço acessá-los é especificando IStream ou IStorage como o identificador de interface em uma chamada para o método IMAPIProp::OpenProperty . Por exemplo, os clientes chamam OpenProperty com PR_ATTACH_DATA_BIN como a marca de propriedade e IID_IStream como o identificador de interface para acessar um anexo binário em uma mensagem.

Clientes e provedores de serviços podem implementar seus próprios objetos de fluxo e armazenamento ou chamar funções de API para acessar implementações fornecidas por MAPI ou COM. Como as implementações fornecidas atendem à maioria das finalidades, os clientes e os provedores de serviços raramente precisam criar seus próprios.

Quando um cliente chama OpenProperty em um objeto MAPI para acessar uma de suas propriedades por meio de um objeto de armazenamento, o provedor de serviços normalmente abrirá o objeto de armazenamento no modo direto. No entanto, isso é típico, em vez de um comportamento necessário. Os clientes devem assumir que todos os objetos de armazenamento abertos ou criados por provedores de serviços são transacionados e exigem uma chamada para IStorage::Commit. Eles também devem lembrar que as alterações nos objetos de armazenamento não serão permanentes até que chamem IMAPIProp::SaveChanges após o Commit final para salvar o objeto MAPI. Para obter mais informações, consulte IMAPIProp::SaveChanges.

MAPI e COM fornecem várias funções de API para definir ou acessar objetos de armazenamento e fluxo. As funções comumente usadas são descritas na tabela a seguir.

Funções para acessar objetos de armazenamento e Stream

Function Description
HrIStorageFromStream
Cria um objeto de armazenamento para acessar um objeto de bytes de fluxo ou bloqueio.
OpenIMsgOnIStg
Cria um objeto de mensagem para acessar um objeto de armazenamento.
OpenStreamOnFile
Cria um objeto stream para acessar um arquivo.
WrapCompressedRTFStream
Cria um objeto de fluxo que contém a versão compactada ou não compactada de um fluxo que contém o texto avançado de uma mensagem.

Para recuperar os nomes dos fluxos em um determinado substorage

  1. Chame o método IStorage::EnumElements da substorage para obter uma interface IEnumSTATSTG .

  2. Chame IEnumSTATSTG::Avançar com o máximo de estruturas STATSTG por vez possível. Se você pedir 100 por vez, o Next geralmente retornará S_FALSE com o conteúdo do pceltFetched definido como o número que foi realmente recuperado.

  3. Verifique as estruturas STATSTG sinalizadas com STGTY_STREAM.

  4. Libere o parâmetro pwcsName .

Para criar um objeto de armazenamento para acessar um objeto de bytes de fluxo ou bloqueio existente

Para criar um objeto de mensagem para acessar um objeto de armazenamento existente

  • Provedores de serviço e clientes chamam OpenIMsgOnIStg. O objeto de mensagem criado difere dos objetos de mensagem normalmente criados por provedores de armazenamento de mensagens na medida em que não dá suporte a todos os métodos de interface IMessage : IMAPIProp , como IMessage::SubmitMessage. Um parâmetro de entrada opcional para OpenIMsgOnIStg é uma função de retorno de chamada que está em conformidade com o protótipo MSGCALLRELEASE . Essa função é chamada pelo novo objeto de mensagem quando a contagem de referência da mensagem atinge zero. Implementar uma função MSGCALLRELEASE pode ser útil para executar o processamento final antes que a nova mensagem seja completamente removida.

OpenStreamOnFile é comumente usado para armazenar anexos de arquivo porque cria um fluxo que lê e grava em um arquivo. AbraProperty com PR_ATTACH_DATA_BIN à medida que a marca de propriedade cria um fluxo para armazenar dados de anexo binário.

Para compactar ou descomprimir um fluxo que contém texto de mensagem no Formato de Texto Rico

  • Os clientes chamam WrapCompressedRTFStream. WrapCompressedRTFStream cria um fluxo que envolve o fluxo RTF. O fluxo de wrapper não implementa todos os métodos IStream ; os seguintes métodos são excluídos: Buscar, SetSize, Reverter, LockRegion, UnlockRegion, Stat e Clone. Isso ocorre porque os objetos de fluxo criados por WrapCompressedRTFStream não dão suporte a SetSize ou Stat, não há uma maneira fácil de estender ou recuperar seu tamanho. A melhor estratégia é escolher um tamanho de buffer razoável e ler ou gravar em um loop.

Observação

O COM tem uma implementação de objeto de armazenamento com base em uma matriz de bytes que retorna um objeto IEnumSTATSTG do método EnumElements que é problemático. Em particular, o método QueryInterface não funciona corretamente. Os provedores de serviço que implementam seus próprios objetos de armazenamento usando a implementação COM devem criar um wrapper fino para o objeto IEnumSTATSTG que encaminha chamadas para os métodos IEnumSTATSTG subjacentes, mas implementa seus próprios métodos AddRef, Release, QueryInterface e Clone .