다음을 통해 공유


IStorage의 이름

속성 집합은 IPropertySetStorage 인터페이스에서 FMTID(형식 식별자)로 식별됩니다. IStorage 인터페이스에서 속성 집합의 이름은 최대 길이가 32자인 null로 끝나는 유니코드 문자열로 지정됩니다. 상호 운용성을 사용하도록 설정하려면 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 문서 요약 정보 및 사용자 정의 속성.

참고

DocumentSummaryInformationUserDefined 속성 집합은 두 개의 섹션이 포함되어 있다는 측면에서 고유합니다. 다른 속성 집합에서는 여러 섹션이 허용되지 않습니다. 자세한 내용은 구조적 스토리지 직렬화된 속성 집합 형식DocumentSummaryInformation 및 사용자 정의 속성 집합을 참조하세요. 첫 번째 섹션은 COM의 일부로 정의되었습니다. 두 번째는 Microsoft Office에서 정의했습니다.

FMTID가 잘 알려진 값이 아닌 경우 다음 절차를 사용하여 알고리즘으로 문자열 이름을 형성합니다.

문자열 이름을 알고리즘으로 형성하려면

  1. 필요한 경우 FMTID를 little-endian 바이트 순서로 변환합니다.
  2. FMTID의 128비트를 가져와서 각 바이트를 함께 연결하여 하나의 긴 비트 문자열로 간주합니다. 128비트 값의 첫 번째 비트는 FMTID 메모리의 첫 번째 바이트 중 가장 중요한 비트입니다. 128비트 값의 마지막 비트는 FMTID 메모리의 마지막 바이트 중 가장 중요한 비트입니다. 끝에 0비트 2개를 추가하여 이러한 128비트에서 130비트까지 확장합니다.
  3. 130비트 를 5비트 그룹으로 나눕니다. 이러한 그룹은 26개입니다. 각 그룹을 역비트 우선 순위가 있는 정수로 간주합니다. 예를 들어 128비트 중 첫 번째 비트는 5비트인 첫 번째 그룹의 가장 중요한 비트입니다. 128비트 중 다섯 번째는 첫 번째 그룹에서 가장 중요한 비트입니다.
  4. 이러한 각 정수는 ABCDEFGHIJKLMNOPQRSTUVWXYZ012345의 배열에 인덱스로 매핑합니다. 그러면 대문자와 숫자만 사용하는 26개의 유니코드 문자 시퀀스가 생성됩니다. 대/소문자를 구분하고 대/소문자를 구분하지 않는 고려 사항이 적용되지 않으므로 각 문자가 모든 로캘에서 고유하게 됩니다.
  5. "\005" 문자열을 총 27자의 길이로 이러한 26자 앞에 연결하여 최종 문자열을 만듭니다.

다음 예제 코드는 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 요소가 있는 경우 이 요소가 사용됩니다. 그렇지 않으면 열기가 실패합니다.

새 속성 집합을 만들 때 위의 매핑은 사용된 문자열 이름을 결정합니다.