Partager via


Considérations relatives au stockage des propriétés

IPropertyStorage ::ReadMultiple lit autant de propriétés spécifiées dans le tableau rgpspec que dans le jeu de propriétés. Tant que l’une des propriétés demandées est lue, une demande de récupération d’une propriété qui n’existe pas n’est pas une erreur. Au lieu de cela, cela doit entraîner l’écriture de VT_EMPTY pour cette propriété dans le tableau rgvar[] lors du retour. Lorsqu’aucune des propriétés demandées n’existe, la méthode doit retourner S_FALSE et définir VT_EMPTY dans chaque PROPVARIANT. Si une autre erreur est retournée, aucune valeur de propriété n’est récupérée et l’appelant n’a pas besoin de s’inquiéter de les libérer.

Le paramètre rgpspec est un tableau de structures PROPSPEC, qui spécifient pour chaque propriété son identificateur de propriété ou, le cas échéant, un identificateur de chaîne. Vous pouvez mapper une chaîne à un identificateur de propriété en appelant IPropertyStorage ::WritePropertyNames. Toutefois, l’utilisation des identificateurs de propriété est susceptible d’être beaucoup plus efficace que l’utilisation de chaînes.

Les propriétés demandées par le nom de chaîne (PRSPEC_LPWSTR) sont mappées sans respect de la casse aux identificateurs de propriété (ID), car elles sont spécifiées dans le jeu de propriétés actuel (et en fonction des paramètres régionaux système actuels).

Lorsque le type de propriété est VT_LPSTR et que la propriété est lue à partir d’un jeu de propriétés ANSI, autrement dit, la page de codes du jeu de propriétés est définie sur quelque chose d’autre que Unicode, la valeur de la propriété utilise la même page de codes que le jeu de propriétés. Lorsqu’une propriété VT_LPSTR est lue à partir d’un jeu de propriétés Unicode, la valeur de la propriété utilise la page de codes ANSI par défaut actuelle du système, autrement dit, la page de codes retournée par la fonction GetACP.

Un PROPVARIANT, à l’exception de ceux qui sont des pointeurs vers des flux et des stockages, est appelé un PROPVARIANT simple. Ces simples PROPVARIANTreçoivent les données par valeur. Par conséquent, un appel à IPropertyStorage ::ReadMultiple fournit une copie des données que l’appelant possède ensuite. Pour créer ou mettre à jour ces propriétés, appelez IPropertyStorage ::WriteMultiple.

En revanche, les types de variantes VT_STREAM, VT_STREAMED_OBJECT, VT_STORAGE et VT_STORED_OBJECT sont des propriétés non simples, car au lieu de fournir une valeur, la méthode récupère un pointeur vers l’interface indiquée, à partir de laquelle les données peuvent ensuite être lues. Ces types permettent de stocker de grandes quantités d’informations par le biais d’une propriété unique. Il existe plusieurs problèmes qui surviennent lors de l’utilisation de propriétés non simples.

Pour créer ces propriétés, comme pour les autres propriétés, appelez IPropertyStorage ::WriteMultiple. Au lieu d’appeler la même méthode à mettre à jour, toutefois, il est plus efficace d’appeler d’abord IPropertyStorage ::ReadMultiple pour obtenir le pointeur d’interface vers le flux ou le stockage, puis écrire des données à l’aide du IStream ou méthodes IStorage. Un flux ou un stockage ouvert via une propriété est toujours ouvert en mode direct, de sorte qu’un niveau supplémentaire de transaction imbriquée n’est pas introduit. Toutefois, il peut y avoir une transaction sur l’ensemble de la propriété définie, selon la façon dont elle a été ouverte ou créée via IPropertySetStorage. En outre, les balises d’accès et de partage spécifiées lorsque le jeu de propriétés est ouvert ou créé sont passés aux flux ou stockages basés sur des propriétés.

Les durées de vie des pointeurs de flux ou de stockage basés sur des propriétés, bien que théoriquement indépendantes de leurs IPropertyStorage et IPropertySetStorage pointeurs, en fait, dépendent efficacement d’eux. Les données visibles par le biais du flux ou du stockage sont liées à la transaction sur l’objet de stockage de propriété à partir duquel elle est récupérée, tout comme pour un objet de stockage (prenant en charge IStorage) avec un flux contenu et des sous-objets de stockage. Si la transaction sur l’objet parent est abandonnée, les IStream existants et pointeurs IStorage subordonnés à cet objet ne sont plus accessibles. Étant donné que IPropertyStorage est la seule interface de l’objet de stockage de propriétés, la durée de vie utile du contenu IStream et pointeurs IStorage est limitée par la durée de vie de l’interface IPropertyStorage.

L’implémentation doit également traiter la situation dans laquelle la même propriété de flux ou de stockage est demandée plusieurs fois par le biais du même IPropertyStorage instance d’interface. Par exemple, dans l’implémentation du fichier composé COM, l’ouverture réussit ou échoue selon que la propriété est déjà ouverte ou non.

Un autre problème est que plusieurs ouvertures s’ouvrent en mode transactionné. Le résultat dépend du niveau d’isolation spécifié par le biais d’un appel à méthodes IPropertySetStorage , (Open ou Méthode Create, via les indicateurs STGM) au moment où le stockage de propriétés a été ouvert.

Si l’appel pour ouvrir le jeu de propriétés spécifie l’accès en lecture-écriture, IStorage et propriétés IStream-valued sont toujours ouvertes avec un accès en lecture-écriture. Les données peuvent ensuite être écrites via ces interfaces, en modifiant la valeur de la propriété, ce qui est le moyen le plus efficace de mettre à jour ces propriétés. La valeur de propriété elle-même n’a pas de niveau supplémentaire d’imbrication des transactions. Les modifications sont donc limitées sous la transaction (le cas échéant) sur l’objet de stockage de propriété.

Propriétés de stockage et de flux

Pour écrire un flux ou un objet de stockage dans un jeu de propriétés, le jeu de propriétés doit avoir été créé comme non simple. Pour plus d’informations sur les ensembles de propriétés simples et non simples, consultez la section intitulée Stockage et Stream Objects pour un jeu de propriétés. Les types de propriétés suivants, comme spécifié dans le champ vt des éléments de tableau rgvar, sont des types de flux ou de stockage : VT_STREAM, VT_STORAGE, VT_STREAMED_OBJECT, VT_STORED_OBJECT.

Pour écrire un flux ou un objet de stockage en tant que propriété dans un jeu de propriétés non simple, appelez IPropertyStorage ::WriteMultiple. Bien que vous appeliez également cette méthode pour mettre à jour des propriétés simples, il n’est pas un moyen efficace de mettre à jour les objets de flux et de stockage dans un jeu de propriétés. Cela est dû au fait que la mise à jour de l’une de ces propriétés via un appel à WriteMultiple crée dans l’objet de stockage de propriétés une copie des données passées, et les IStorage ou pointeurs IStream ne sont pas conservés au-delà de la durée de cet appel. Il est généralement plus efficace de mettre à jour les objets de flux ou de stockage directement en appelant IPropertyStorage ::ReadMultiple pour obtenir le pointeur d’interface vers le flux ou le stockage, puis en écrivant des données via les méthodes IStream ou IStorage.

Par exemple, vous pouvez appeler IPropertyStorage ::WriteMultiple pour écrire un flux de NULL ou un objet de stockage. L’implémentation crée ensuite un objet vide dans le jeu de propriétés. Vous pouvez ensuite accéder à cet objet en appelant IPropertyStorage ::ReadMultiple. Lorsque vous avez terminé la mise à jour de cet objet, vous n’avez pas besoin de l’écrire dans le jeu de propriétés, car vos mises à jour allaient directement dans le jeu de propriétés.

Un flux ou un stockage ouvert via une propriété est toujours ouvert en mode direct, de sorte qu’un niveau supplémentaire de transaction imbriquée n’est pas introduit. Il peut toujours y avoir une transaction sur la propriété définie dans son ensemble. (Par exemple, si le IPropertyStorage a été obtenu en appelant IPropertySetStorage ::Open avec l’indicateur de STGM_TRANSACTED défini dans le paramètre grfmode.) En outre, un flux ou un stockage basé sur des propriétés est ouvert en mode lecture-écriture, si possible, en fonction du mode sur le jeu de propriétés ; sinon, le mode lecture est utilisé.

Comme mentionné précédemment, lorsqu’un flux ou un objet de stockage est écrit dans un jeu de propriétés avec la méthode WriteMultiple, une copie de l’objet est effectuée. Lorsqu’une telle copie est effectuée sur un objet de flux, l’opération de copie démarre à la position de recherche actuelle de la source. La position de recherche n’est pas définie en cas d’échec, mais en cas de réussite, elle se trouve à la fin du flux ; le pointeur de recherche n’est pas restauré à sa position d’origine.

Si une propriété de flux ou de stockage a été lue à partir d’un jeu de propriétés avec readMultiple, est toujours ouverte et qu’un appel ultérieur à WriteMultiple pour la même propriété est effectué, l’opération WriteMultiple réussit. Le flux ouvert précédemment ou la propriété de stockage est placée dans l’état rétabli (tous les appels à celui-ci retournent STG_E_REVERTED erreur).

Si la méthode WriteMultiple retourne une erreur lors de l’écriture d’un tableau de propriétés ou même des propriétés non simples individuelles, la quantité de données réellement écrites n’est pas définie.

Propriétés de référence

Si une structure PROPVARIANT spécifiée inclut l’indicateur VT_BYREF dans son membre vt, la propriété associée est une propriété de référence. Une propriété de référence est automatiquement déréférente avant d’écrire la valeur dans le jeu de propriétés. Par exemple, si le membre vt de la structure PROPVARIANT spécifie une valeur de type VT_BYREF | VT_I4, la valeur réelle écrite est un type VT_I4. Un appel ultérieur à la méthode IPropertyStorage ::ReadMultiple retourne une valeur comme VT_I4. L’utilisation de propriétés de référence est similaire à l’appel de la fonction VariantCopyInd. VariantCopyInd libère la variante de destination et effectue une copie du VARIANTARG source, effectuant l’indirection nécessaire si la source est spécifiée pour être VT_BYREF. Cette fonction est utile lorsqu’une copie d’une variante est nécessaire et pour garantir qu’elle n’est pas VT_BYREF, par exemple lors de la gestion des arguments dans une implémentation de IDispatch ::Invoke.

Remarques sur les appelants

Il est recommandé de créer des jeux de propriétés en tant qu’Unicode, en ne définissant pas l’indicateur PROPSETFLAG_ANSI dans le paramètre grfFlags de IPropertySetStorage ::Create. Il est également recommandé d’éviter d’utiliser des valeurs VT_LPSTR et d’utiliser des valeurs VT_LPWSTR à la place. Lorsque la page de codes du jeu de propriétés est Unicode, VT_LPSTR valeurs de chaîne sont converties en Unicode lorsqu’elles sont stockées et de nouveau en valeurs de chaîne multioctets lors de la récupération. Lorsque la page de codes du jeu de propriétés n’est pas Unicode, les noms de propriétés, les chaînes VT_BSTR et les valeurs de propriété non simples sont convertis en chaînes multioctets lorsqu’elles sont stockées et converties en Unicode lors de la récupération, toutes à l’aide de la page de codes ANSI système actuelle.

Remarques sur les implémenteurs

Lors de l’allocation d’un identificateur de propriété, l’implémentation peut choisir n’importe quelle valeur actuellement en cours d’utilisation dans le jeu de propriétés pour un identificateur de propriété, tant qu’elle n’est pas 0 ou 1 ou supérieure à 0x80000000, qui sont toutes des valeurs réservées. Le paramètre propidNameFirst établit une valeur minimale pour les identificateurs de propriété au sein du jeu et doit être supérieur à 1 et inférieur à 0x80000000. Voir la section Remarques ci-dessus.

IPropertyStorage-Compound d’implémentation de fichiers

IPropertyStorage-NTFS d’implémentation du système de fichiers

implémentation autonome IPropertyStorage