프로그래밍2007.07.23 22:21
COM 객체에 영속성을 부여하기 위한 방법

IPersist
COM 객체가 영속성 객체임을 구현

인터페이스를 상속받은 인터페이스
IPersistStream : 스트림 사용
IPersistStreamInit : IPersistStream에서 초기화를 위해 InitNew 메쏘드 추가
IPersistMemory : 스트림 대신에 메모리
IPersistStorage : 스토리지를 사용
IPersistFile : 파일을 사용
IPersistPropertyBag2 : 프로퍼티 백 사용 ( ActiveX 콘트롤 속성값 )
IPersistMoniker : 모니커 사용
IPersistHistory : 사용자 웹사이트 히스토리 저장(익스플로러)
위 인터페이스를 COM 객체에 구현하여 영속성을 부여 함

ATL에서는 위 인터페이스들 중에서 구현 클래스를 제공한다
IPersistStreamInitImpl
IPersistStoreageImpl
IPersistPropertyBagImpl

구현
IPersistStream을 구현할시에 CLSID도 같이 스트림에 저장하고 빼온다
OleSaveToStream, OleLoadFromStream 헬퍼 함수 사용

IStream
IPersistStream, IPersistStreamInit 인터페이스를 구현하는 COM 영속성 객체에 실제로 스트림에 읽거나 쓰는 클라이언트 구현 인터페이스
IPersistStream, IPersistStreamInit 의 Save , Load 메소드의 인자로 IStream 인터페이스가 전달됨

사용 방법
// COM 객체생성
IUnknown * pUnknown;
... CoCreateInstance 중략

// IPersistStreamInit 인터페이스 가져옴
CComPtr <IPersistStreamInit> pPersistStreamInit;
hr = pUnknown->QueryInterface(IID_IPersistStreamInit, (void**)&pPersistStreamInit);

// 메모리 기반 스트림
CComPtr <IStream> pStream;
hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);

// 초기화
hr = pPersistStreamInit->InitNew();

// 객체를 스트림으로 저장
hr = pPersistStreamInit->Save(pStream, TRUE);

// 포인터를 처음으로 옮김
LARGE_INTEGER zero = {0, 0};
hr = pStream->Seek(zero, STREAM_SEEK_SET, NULL);

// 새로운 객체 생성
// IPersistStreamInit 인터페이스를 가져옴

// 스트림에서 객체 가져옴
hr = pPersistStreamInit->Load(pStream);

구현 방법
CreateStreamOnHGlobal : 일반적인 IStream 인터페이스의 구현을 얻음 ( 글로벌 메모리의 블록에 기반한 스트림 객체 생성 ) <-> GetHGlobalFromStream
구조화된 저장 서비스 : 디스크 기반의 파일로 스트림 저장

데이터를 저정하기 위한 표준화 되고 구조적인 형식으로 단일 파일내에 데이터를 저장
IStorage 인터페이스를 이용하여 IStream 인터페이스 객체 생성

// 구조화된 저장소 파일을 생성 하거나 오픈하고 IStorage 인터페이스를 얻어옴
CComPtr IStorage pStorage;
hr = StgCreateStorageEx(L"C:\\test.stg", STGM_DIRECT | STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, STGFMT_STORAGE, 0, 0, IID_IStorage, (void**)&pStorage);

// Stream 객체를 생성하고 IStream 인터페이스를 얻어옴
CComPtr IStream pStream;
hr = pStorage->CreateStream(L"TestStream", STGM_DIRECT | STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStream);

// 파일에 데이터를 쓴다.
ULONG bytes_written;
char data[] = "HELLO THERE!";
pStream->Write(data, strlen(data), &bytes_written);

Property ( 속성 )
표준화된 방법 으로 요약정보를 저장하는 데 사용할 수 있는 속성 집합 형식 ( Ex : 파일 요약 정보 )

// IStorage 인터페이스로 IProperySetStorage 인터페이스를 가져옴
CComPtr <IPropertySetStorage> pPropertySetStorage;
pStorage->QueryInterface(IID_IPropertySetStorage, (void*)&pPropertySetStorage);

// IPropertySetStorage 인터페이스를 이용하여 IPropertyStorage 인터페이스 객체 생성
CComPtr <IPropertyStorage> pPropertyStorage;
pPropertyStorage->Create(FMTID_SummaryInformation, NULL, PROPSETFLAG_ANSI, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, &pPropertyStorage);

속성집합을 정의
PROPSPEC(속성구별자 또는 문자열 이름) , PROPVARIANT(속성 값) 구조체 이용

PROPSPEC ps;
ps.ulKind = PRSPEC_PROPID;
ps.propid = PIDSI_AUTHOR;

PROPVARIANT pv;
pv.vt = VT_LPSTR;
pv.pszVal = "Anna";

hr = pPropertyStorage->WriteMultiple(1, &ps, &pv, 0);

MSDN : http://msdn2.microsoft.com/en-us/library/aa380369.aspx (Structured Storage)
Posted by 꿍스