Имена в IStorage

Набор свойств идентифицируется с помощью идентификатора формата (FMTID) в интерфейсе IPropertySetStorage . В интерфейсе IStorage набор свойств именуется с строкой Юникода, заканчивающейся null, длиной не более 32 символов. Чтобы обеспечить взаимодействие, необходимо установить сопоставление между FMTID и соответствующей строкой Юникода, завершающейся null.

Преобразование набора свойств из FMTID в строковое имя

При преобразовании из FMTID в соответствующее строковое имя Юникода сначала убедитесь, что FMTID является хорошо известным значением, перечисленным в следующей таблице. Если да, используйте соответствующее известное строковое имя.

FMTID Имя строки Семантика
F29F85E0-4FF9-1068-AB91-08002B27B3D9 "\005SummaryInformation" Сводные сведения о COM2
D5CDD502-2E9C-101B-9397-08002B2CF9AE D5CDD505-2E9C-101B-9397-08002B2CF9AE
"\005DocumentSummaryInformation" Сводные сведения о документе Office и определяемые пользователем свойства.

Примечание

Набор свойств DocumentSummaryInformation и UserDefined уникален тем, что содержит два раздела. Несколько разделов не допускаются в других наборах свойств. Дополнительные сведения см. в разделах Формат сериализованного набора свойств структурированного хранилища и Наборы свойств DocumentSummaryInformation и UserDefined. Первый раздел был определен как часть COM; вторая была определена в Microsoft Office.

Если FMTID не является известным значением, используйте следующую процедуру для алгоритмического формирования имени строки.

Алгоритмическое формирование имени строки

  1. При необходимости преобразуйте FMTID в байтовый порядок с минимальным порядком байтов.
  2. Возьмите 128 бит FMTID и рассмотрите их как одну длинную битовую строку, сцепляя каждый из байтов вместе. Первый бит 128-разрядного значения является наименее значимым битом первого байта в памяти FMTID; последний бит 128-разрядного значения является наиболее значительным битом последнего байта в памяти FMTID. Расширьте эти 128 бит до 130 бит, добавив два нулевых бита в конец.
  3. Разделите 130 битов на группы по пять битов; таких групп будет 26. Каждую группу следует рассматривать как целое число с обратным битовым приоритетом. Например, первый из 128 бит является наименее значимым битом первой группы из пяти битов; пятый из 128 бит является самым значительным битом первой группы.
  4. Сопоставьте каждое из этих целых чисел как индекс с массивом из тридцати двух символов: ABCDEFGHIJKLMNOPQRSTUVWXYZ012345. Это дает последовательность из 26 символов Юникода, которая использует только символы верхнего регистра и цифры. Рекомендации с учетом регистра и без учета регистра не применяются, что приводит к уникальности каждого символа в любом языковом стандарте.
  5. Создайте последнюю строку, сцепляя строку "\005" с передней частью этих 26 символов общей длиной 27 символов.

В следующем примере кода показано, как сопоставить fmTID со строкой свойства.

#define CBIT_BYTE        8
#define CBIT_CHARMASK    5
#define CCH_MAP          (1 << CBIT_CHARMASK)    // 32
#define CHARMASK         (CCH_MAP - 1)           // 0x1f
 
CHAR awcMap[CCH_MAP + 1] = "abcdefghijklmnopqrstuvwxyz012345";
 
WCHAR MapChar(ULONG I) {
    return((WCHAR) awcMap[i & CHARMASK]);
    }
 
VOID GuidToPropertyStringName(GUID *pguid, WCHAR awcname[]) {
    BYTE *pb = (BYTE *) pguid;
    BYTE *pbEnd = pb + sizeof(*pguid);
    ULONG cbitRemain = CBIT_BYTE;
    WCHAR *pwc = awcname;
 
    *pwc++ = ((WCHAR) 0x0005);
    while (pb < pbEnd) {
        ULONG i = *pb >> (CBIT_BYTE - cbitRemain);
        if (cbitRemain >= CBIT_CHARMASK) {
            *pwc = MapChar(i);
            if (cbitRemain == CBIT_BYTE && 
                                    *pwc >= L'a' && *pwc <= L'z')
                {
                *pwc += (WCHAR) (L'A' - L'a');
                }
            pwc++;
            cbitRemain -= CBIT_CHARMASK;
            if (cbitRemain == 0) {
                pb++;
                cbitRemain = CBIT_BYTE;
                }
            }
        else {
            if (++pb < pbEnd) {
                i |= *pb << cbitRemain;
                }
            *pwc++ = MapChar(i);
            cbitRemain += CBIT_BYTE - CBIT_CHARMASK;
            }
        }
    *pwc = L'\0';
    }

Преобразование набора свойств из строкового имени в FMTID

Преобразователи имен строк свойств в идентификаторы GUID должны принимать строчные буквы как синонимы своих аналогов в верхнем регистре.

В следующем примере кода показано, как сопоставить строку свойства с FMTID.

#include "stdafx.h"
#define _INC_OLE
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define CBIT_CHARMASK 5
#define CBIT_BYTE     8
#define CBIT_GUID    (CBIT_BYTE * sizeof(GUID))
#define CWC_PROPSET  (1 + (CBIT_GUID + CBIT_CHARMASK-1)/CBIT_CHARMASK)
#define WC_PROPSET0  ((WCHAR) 0x0005)
#define CCH_MAP      (1 << CBIT_CHARMASK)        // 32
#define CHARMASK     (CCH_MAP - 1)            // 0x1f
CHAR awcMap[CCH_MAP + 1] = "abcdefghijklmnopqrstuvwxyz012345";
#define CALPHACHARS  ('z' - 'a' + 1)

GUID guidSummary =
{ 0xf29f85e0,0x4ff9, 0x1068,
{ 0xab, 0x91, 0x08, 0x00, 0x2b, 0x27, 0xb3, 0xd9 } };

WCHAR wszSummary[] = L"SummaryInformation";

GUID guidDocumentSummary =
    { 0xd5cdd502,
      0x2e9c, 0x101b,
      { 0x93, 0x97, 0x08, 0x00, 0x2b, 0x2c, 0xf9, 0xae } };

WCHAR wszDocumentSummary[] = L"DocumentSummaryInformation";
__inline WCHAR

MapChar(IN ULONG i)
{
    return((WCHAR) awcMap[i & CHARMASK]);
}

ULONG PropertySetNameToGuid(
    IN ULONG cwcname,
    IN WCHAR const awcname[],
    OUT GUID *pguid)
{
    ULONG Status = ERROR_INVALID_PARAMETER;
    WCHAR const *pwc = awcname;

    if (pwc[0] == WC_PROPSET0)
    {
        //Note: cwcname includes the WC_PROPSET0, and
        //sizeof(wsz...) includes the trailing L'\0', but
        //the comparison excludes both the leading
        //WC_PROPSET0 and the trailing L'\0'.
        if (cwcname == sizeof(wszSummary)/sizeof(WCHAR) &&
            wcsnicmp(&pwc[1], wszSummary, cwcname - 1) == 0)
        {
            *pguid = guidSummary;
            return(NO_ERROR);
        }
        if (cwcname == CWC_PROPSET)
        {
            ULONG cbit;
            BYTE *pb = (BYTE *) pguid - 1;
            ZeroMemory(pguid, sizeof(*pguid));
            for (cbit = 0; cbit < CBIT_GUID; cbit += 
            CBIT_CHARMASK)
            {
                ULONG cbitUsed = cbit % CBIT_BYTE;
                ULONG cbitStored;
                WCHAR wc;
                if (cbitUsed == 0)
                {
                    pb++;
                }
                wc = *++pwc - L'A';        //assume uppercase
                if (wc > CALPHACHARS)
                {
                    wc += (WCHAR) (L'A' - L'a'); //try lowercase
                    if (wc > CALPHACHARS)
                    {
                        wc += L'a' - L'0' + CALPHACHARS; 
                        if (wc > CHARMASK)
                        {
                            goto fail;       //invalid character
                        }
                    }
                }
                *pb |= (BYTE) (wc << cbitUsed);
                cbitStored = min(CBIT_BYTE - cbitUsed, 
                CBIT_CHARMASK);

                //If the translated bits will not fit in the 
                //current byte
                if (cbitStored < CBIT_CHARMASK)
                {
                    wc >>= CBIT_BYTE - cbitUsed;
                    if (cbit + cbitStored == CBIT_GUID)
                    {
                       if (wc != 0)
                       {
                           goto fail;        //extra bits
                       }
                       break;
                    }
                    pb++;
                    *pb |= (BYTE) wc;
                }
           }
           Status = NO_ERROR;
      }
    }
fail:
    return(Status);
}

При попытке открыть существующий набор свойств в IPropertySetStorage::Open (корневой) FMTID преобразуется в строку, как описано выше. Если элемент IStorage с таким именем существует, он используется. В противном случае открытие завершается ошибкой.

При создании нового набора свойств приведенное выше сопоставление определяет используемое имя строки.