속성 스토리지 고려 사항
IPropertyStorage::ReadMultiple 속성 집합에 있는 것처럼 rgpspec 배열에 지정된 많은 속성을 읽습니다. 요청된 속성을 읽는 한 존재하지 않는 속성을 검색하는 요청은 오류가 아닙니다. 대신 반환 시 해당 속성에 대한 VT_EMPTY rgvar[] 배열에 기록되어야 합니다. 요청된 속성이 없으면 메서드는 S_FALSE 반환하고 각 PROPVARIANTVT_EMPTY 설정해야 합니다. 다른 오류가 반환되면 속성 값이 검색되지 않으며 호출자는 오류를 해제하는 것에 대해 걱정할 필요가 없습니다.
rgpspec 매개 변수는 속성 식별자 또는 문자열 식별자가 할당된 경우 각 속성에 대해 지정하는 PROPSPEC 구조의 배열입니다. IPropertyStorage::WritePropertyNames호출하여 문자열을 속성 식별자에 매핑할 수 있습니다. 그러나 속성 식별자의 사용은 문자열 사용보다 훨씬 더 효율적일 수 있습니다.
문자열 이름(PRSPEC_LPWSTR)에서 요청하는 속성은 현재 속성 집합(및 현재 시스템 로캘에 따라)에 지정된 속성 식별자(ID)에 대/소문자를 구분하지 않습니다.
속성 형식이 VT_LPSTR ANSI 속성 집합에서 속성을 읽는 경우, 즉 속성 집합의 코드 페이지가 유니코드 이외의 값으로 설정되면 속성 값은 속성 집합과 동일한 코드 페이지를 사용합니다. 유니코드 속성 집합에서 VT_LPSTR 속성을 읽을 때 속성 값은 시스템의 현재 기본 ANSI 코드 페이지, 즉 GetACP 함수에서 반환된 코드 페이지를 사용합니다.
스트림 및 스토리지에 대한 포인터인 PROPVARIANT단순 PROPVARIANT호출합니다. 이러한 간단한 PROPVARIANT값으로 데이터를 수신하므로 IPropertyStorage::ReadMultiple 호출하면 호출자가 소유한 데이터의 복사본이 제공됩니다. 이러한 속성을 만들거나 업데이트하려면 IPropertyStorage::WriteMultiple호출합니다.
반면, 변형 형식은 VT_STREAM, VT_STREAMED_OBJECT, VT_STORAGE 및 VT_STORED_OBJECT 단순하지 않은 속성입니다. 이 속성은 값을 제공하는 대신 지정된 인터페이스에 대한 포인터를 검색하여 데이터를 읽을 수 있기 때문입니다. 이러한 형식은 단일 속성을 통해 많은 양의 정보를 저장하도록 허용합니다. 비심플 속성을 사용할 때 발생하는 몇 가지 문제가 있습니다.
다른 속성과 마찬가지로 이러한 속성을 만들려면 IPropertyStorage::WriteMultiple호출합니다. 그러나 업데이트할 동일한 메서드를 호출하는 대신 먼저 IPropertyStorage::ReadMultiple 호출하여 스트림 또는 스토리지에 대한 인터페이스 포인터를 가져와서 IStream 또는 IStorage 메서드를 사용하여 데이터를 작성하는 것이 더 효율적입니다. 속성을 통해 열린 스트림 또는 스토리지는 항상 직접 모드로 열리므로 중첩된 트랜잭션의 추가 수준이 도입되지 않습니다. 그러나 IPropertySetStorage통해 열거나 만든 방법에 따라 속성 집합 전체에 대한 트랜잭션이 여전히 있을 수 있습니다. 또한 속성 집합을 열거나 만들 때 지정된 액세스 및 공유 모드 태그가 속성 기반 스트림 또는 스토리지에 전달됩니다.
속성 기반 스트림 또는 스토리지 포인터의 수명은 이론적으로 연결된 IPropertyStorage 및 IPropertySetStorage 포인터와 독립적이지만 실제로는 포인터에 따라 달라집니다. 스트림 또는 스토리지를 통해 표시되는 데이터는 포함된 스트림 및 스토리지 하위 개체가 있는 스토리지 개체(IStorage지원)와 마찬가지로 검색되는 속성 스토리지 개체의 트랜잭션과 관련이 있습니다. 부모 개체의 트랜잭션이 중단되면 기존 IStream 및 IStorage 포인터가 해당 개체에 종속된 더 이상 액세스할 수 없습니다. IPropertyStorage 속성 스토리지 개체의 유일한 인터페이스이므로 포함된 IStream 및 IStorage 포인터의 유용한 수명은 IPropertyStorage 인터페이스의 수명으로 제한됩니다.
또한 구현은 동일한 IPropertyStorage 인터페이스 인스턴스를 통해 동일한 스트림 또는 스토리지 반환 속성이 여러 번 요청되는 상황을 처리해야 합니다. 예를 들어 COM 복합 파일 구현에서 열기는 속성이 이미 열려 있는지 여부에 따라 성공하거나 실패합니다.
또 다른 문제는 트랜잭션 모드에서 여러 개 열립니다. 결과는 속성 스토리지가 열렸을 때 IPropertySetStorage 메서드(Open 또는 Create 메서드를 STGM 플래그를 통해)에 대한 호출을 통해 지정된 격리 수준에 따라 달라집니다.
속성 집합을 열기 위한 호출이 읽기-쓰기 액세스를 지정하는 경우 IStorageIStream-valued 속성을항상 읽기-쓰기 액세스 권한으로 열립니다. 그런 다음, 이러한 인터페이스를 통해 데이터를 작성하여 속성 값을 변경할 수 있으며, 이는 이러한 속성을 업데이트하는 가장 효율적인 방법입니다. 속성 값 자체에는 추가 수준의 트랜잭션 중첩이 없으므로 속성 스토리지 개체의 트랜잭션(있는 경우)에서 변경 내용의 범위가 지정됩니다.
스토리지 및 스트림 속성
속성 집합에 스트림 또는 스토리지 개체를 쓰려면 속성 집합이 비임플로 만들어졌어야 합니다. 단순 및 비임플 속성 집합에 대한 자세한 내용은 속성 집합 Storage 및 Stream 개체 섹션을 참조하세요. rgvar 배열 요소의 vt 필드에 지정된 속성 형식은 VT_STREAM, VT_STORAGE, VT_STREAMED_OBJECT, VT_STORED_OBJECT 스트림 또는 스토리지 형식입니다.
단순하지 않은 속성 집합에서 스트림 또는 스토리지 개체를 속성으로 쓰려면 IPropertyStorage::WriteMultiple호출합니다. 이 메서드를 호출하여 단순 속성을 업데이트하지만 속성 집합에서 스트림 및 스토리지 개체를 업데이트하는 효율적인 방법은 아닙니다. 이는 writeMultiple 호출을 통해 이러한 속성 중 하나를 업데이트하면 속성 스토리지 개체에 전달된 데이터의 복사본이 생성되고 IStorage 또는 IStream 포인터는 이 호출 기간 이후에도 유지되지 않기 때문입니다. 일반적으로 스트림 또는 스토리지에 대한 인터페이스 포인터를 가져오는 IPropertyStorage::ReadMultiple 호출한 다음, IStream 또는 IStorage 메서드를 통해 데이터를 작성하여 스트림 또는 스토리지 개체를 직접 업데이트하는 것이 더 효율적입니다.
예를 들어 IPropertyStorage::WriteMultiple 호출하여 NULL 스트림 또는 스토리지 개체를 작성할 수 있습니다. 그런 다음 구현은 속성 집합에 빈 개체를 만듭니다. 그런 다음 IPropertyStorage::ReadMultiple호출하여 이 개체에 액세스할 수 있습니다. 이 개체 업데이트를 마치면 업데이트가 속성 집합으로 직접 진행되므로 속성 집합에 쓸 필요가 없습니다.
속성을 통해 열린 스트림 또는 스토리지는 항상 직접 모드로 열리므로 중첩된 트랜잭션의 추가 수준이 도입되지 않습니다. 속성 집합 전체에 트랜잭션이 여전히 있을 수 있습니다. 예를 들어 grfmode 매개 변수에 설정된 STGM_TRANSACTED 플래그로 IPropertySetStorage::Open 호출하여 IPropertyStorage 가져온 경우입니다. 또한 속성 집합의 모드를 고려할 때 가능한 경우 속성 기반 스트림 또는 스토리지가 읽기/쓰기 모드로 열립니다. 그렇지 않으면 읽기 모드가 사용됩니다.
앞에서 설명한 것처럼 스트림 또는 스토리지 개체가 WriteMultiple 메서드를 사용하여 속성 집합에 기록되면 개체의 복사본이 만들어집니다. 스트림 개체에서 이러한 복사본이 만들어지면 원본의 현재 검색 위치에서 복사 작업이 시작됩니다. 검색 위치는 실패 시 정의되지 않지만 성공 시 스트림의 끝에 있습니다. 검색 포인터가 원래 위치로 복원되지 않습니다.
ReadMultiple있는 속성 집합에서 스트림 또는 스토리지 속성을 읽은 후에도 계속 열려 있고 동일한 속성에 대해 WriteMultiple후속 호출이 수행되면 WriteMultiple 작업이 성공합니다. 이전에 연 스트림 또는 스토리지 속성은 되돌려진 상태로 배치됩니다(이 속성에 대한 모든 호출은 STG_E_REVERTED 오류를 반환합니다).
WriteMultiple 메서드가 속성 배열 또는 개별 비 단순 속성을 작성할 때 오류를 반환하는 경우 실제로 작성된 데이터의 양은 정의되지 않습니다.
참조 속성
지정된 PROPVARIANT 구조체에 vt 멤버에 VT_BYREF 플래그가 포함된 경우 연결된 속성은 참조 속성입니다. 참조 속성은 속성 집합에 값을 쓰기 전에 자동으로 역참조됩니다. 예를 들어 PROPVARIANT 구조체의 vt 멤버가 VT_BYREF 형식의 값을 지정하는 경우 | VT_I4 작성된 실제 값은 VT_I4 형식입니다. IPropertyStorage::ReadMultiple 메서드에 대한 후속 호출은 값을 VT_I4 반환합니다. 참조 속성을 사용하는 것은 VariantCopyInd 함수를 호출하는 것과 비슷합니다. VariantCopyInd 대상 변형을 해제하고 원본 VARIANTARG의 복사본을 만들어 원본을 VT_BYREF 지정한 경우 필요한 간접 참조를 수행합니다. 이 함수는 변형의 복사본이 필요할 때 유용하며, 예를 들어 IDispatch::Invoke구현에서 인수를 처리할 때와 같이 VT_BYREF 않습니다.
발신자에 대한 참고 사항
IPropertySetStorage::CreategrfFlags 매개 변수에서 PROPSETFLAG_ANSI 플래그를 설정하지 않고 속성 집합을 유니코드로 만드는 것이 좋습니다. 또한 VT_LPSTR 값을 사용하지 않고 대신 VT_LPWSTR 값을 사용하는 것이 좋습니다. 속성 집합 코드 페이지가 유니코드인 경우 VT_LPSTR 문자열 값은 저장될 때 유니코드로 변환되고 검색 시 다시 멀티바이트 문자열 값으로 변환됩니다. 속성 집합의 코드 페이지가 유니코드가 아닌 경우 현재 시스템 ANSI 코드 페이지를 사용하여 속성 이름, VT_BSTR 문자열 및 단순하지 않은 속성 값이 저장될 때 멀티바이트 문자열로 변환되고 검색될 때 유니코드로 다시 변환됩니다.
구현자에 대한 참고 사항
속성 식별자를 할당할 때 구현은 속성 식별자에 대한 속성 집합에서 현재 사용되지 않는 값을 선택할 수 있습니다. 0 또는 1이 아니거나 0x80000000 이상이며 모두 예약된 값입니다. propidNameFirst 매개 변수는 집합 내의 속성 식별자에 대한 최소 값을 설정하며 1보다 크고 0x80000000 미만이어야 합니다. 위의 설명 섹션을 참조하세요.
관련 항목