====== 주요 개념 ====== ===== COM 종류 ===== 인프로세스 서버 : 다른 프로세스에서 생성&실행되는 서버 * DLL의 형태로 로딩되는 함수를 export 해야한다. 아웃오브프로세스 : 별도의 프로세스가 생성되어 실행되는 서버 * 로컬과 리모트로 분류된다. ===== 인터페이스 정의 ===== I로 시작되며, IUnknown 에서 상속되어야 한다. IUnkonwn에 정의되는 기본 메소드 * QueryInterface * AddRef * Release 언어독립성을 유지하기 위해서 상속만을 지원한다. polymorphism은 지원하지 않는 정책 ===== GUID (Global Unique IDentifer) ===== OSF가 제공하는 GUID를 차용 128비트 (16바이트)의 구조체 모든 COM 객체와 해당되는 COM 내부의 인터페이스는 독립적인 GUID를 갖는다. UUID 라고도 부른다. **CLSID : COM 객체의 GUID** **IID : 인터페이스의 GUID** ===== GUID 제어 ===== guiddef.h 에 구조체가 선언되어 있다. typedef struct _GUID { unsigned long Data1, Data2, Data3; unsigned char Data4[ 8 ]; } GUID; 비교기능 * 연산자 ==, IsEqualGUID, IsEqualIID, IsEqualCLSID 구조체이기 때문에 파라미터로 오갈 때에는 레퍼런스 형식으로 사용된다. * REFIID (== const IID&) * COM에 관련 함수의 파라미터는 위의 디파인을 사용한다. ===== GUID 변환 ===== StringFromGUID2 : GUID를 스트링의 형식으로 변경하는 함수 ==== ProgID ==== CLSID의 별명 (alias) 128비트의 코드 형태는 기억하기 어려우므로 문자열 식별자를 제공 * 형식 <컴포넌트 or 라이브러리명>.<객체명>.<버젼> // 예 Excel.Application.10 hkey_classes_root 내부의 각 항목들이 COM의 ProgID 들 ==== ProgID 변환 ==== ProgID로부터 CLSID를 구한다. * 사용함수 HRESULT CLSIDFromProgID( LPOLESTR /*ProgID 문자열*/, LPCLSID /*리턴된 CLSID*/ ); ====== COM 사용 ====== 메모 : COM API 함수는 "Co"로 시작된다. ===== 등록,해제 ===== // 등록 regsvr32 COMServerName.dll // 해제 regsvr32 /u COMServerName.dll ===== 리턴값 ===== 정상 : S_OK (== 0x0L) 에러 : 0x80000000L (== 마이너스 얼마 얼마) ===== 초기화/종료 ===== COM 사용 개시 : CoInitializeEx( NULL, /*dwCoInit*/ ), 첫번째 값은 예약값으로 현재는 널. * CoInitialize() : DCOM 이전에 사용되던 초기화 함수. 현재는 미사용. ===== COM 객체 인스턴스 생성 - CoCreateInstance ===== **CoCreateInstance( CLSID, NULL, CLSCTX_ALL, IID_IUnknown, (void**)&pUnk )** 로 **CLSID와 IID**를 넘겨서 인터페이스 포인터를 구한다. | CLSCTX_ALL | clsid를 검색할 장소 지정 | | IID_IUnknown | 예제로사용된 IID. 사용시에는 얻으려는 인터페이스 아이디 (IID)를 넣는다. | | pUnk | 리턴된 인터페이스 포인터 | - 내부에서는 CoGetClassObject()를 (책에 의하면) 호출하여 COM 객체(클래스객체)를 구한다고 함, 설명하기 위한 예인지는 잘 모르겠지만. - 얻어낸 클래스 객체로부터 사용하려는 인터페이스 인스턴스를 생성 ==== 함수 호출관계 빨리 보기 ==== - CoCreateInstance() - IClassFactory 인터페이스 변수 준비 - CoGetclassObject() - 레지스트리로부터 COM 객체의 경로명과 파일명을 구한다. - CoLoadLibrary()로 COM 객체를 로딩 - GetProcAddress() : "DllGetClassObject" 함수 포인터 얻기 - DllGetClassObject()로 COM 객체와 대응되는 클래스팩토리 COM 객체를 얻어 리턴 - 리턴된 클래스팩토리 COM 객체의 CreateInstance()를 호출 - 작업 종료 ===== COM 객체 인스턴스 생성 - CoGetClassObject ===== CoCreateInstance()에 의해 호출되는 CoGetClassObject()가 하는일 HRESULT CoGetClassObject( __in REFCLSID rclsid, __in DWORD dwClsContext, __in_opt COSERVERINFO pServerInfo, __in REFIID riid, __out LPVOID *ppv ); ==== 기본 ==== - CLSID 에 해당되는 클래스 객체(by CLSID)를 찾아, 해당 객체의 IID_IClassFactory 인터페이스를 얻는다. - 2번째 파라미터 (dwClsContext) * CLSCTX_ALL : InProcServer32 > LocalServer32 에서 순서대로 객체 검색 * CLSCTX_LOCAL_SERVER : LocalServer32에서 검색 ==== CLSID에 해당되는 DLL(또는 다른파일) 얻기 ==== - HKEY_CLASSES_ROOT\CLSID에서 - CLSID 와 같은 키의 **InProcServer32**/**LocalServer32**(OutOfProcess style)에서 COM객체의 경로를 획득 ==== 실제 DLL(또는 다른파일) 로딩하기 ==== 객체 위치(경로)를 구했으면, * 인-프로세스 : CoLoadLibrary()로 해당 DLL 객체를 로딩 * 아웃오브프로세스 : ? 아직 모름 ==== 로딩된 DLL로부터 클래스 객체 얻기 ==== - 로딩된 DLL로 부터 GetProcAddress()를 사용해서 **DllGetClassObject()의 함수포인터**를 구해온다. - DllGetClassObject()의 3번째 파라미터에 최종 클래스 오브젝트 (여기서는 해당 COM 객체의 IID_IClassFactory 인터페이스)를 리턴 받고 - 함수를 종료한다. // 의미전달용 코드 DllGetClassObject( CLSID, IID, (out)ppv ); ===== COM 객체 인스턴스 생성 - 인터페이스(인스턴스) 생성 ===== HRESULT CoGetClassObject( __in REFCLSID rclsid, __in DWORD dwClsContext, __in_opt COSERVERINFO pServerInfo, __in REFIID riid, __out LPVOID *ppv ); CoCreateInstance()를 호출 한뒤, - 내부에서 CoGetClassObject()가 실행되어 IID_IClassFactory 인터페이스를 구했다면, - IID_IClassFactory 인터페이스를 사용해서 - riid (실제로 얻으려는 인터페이스 GUID)에 해당되는 인터페이스를 만든다. (인스턴스를 생성한다.) (IClassFactory*)pClassFactory->CreateInstance( NULL, riid, ppv ); - **최종 값은 ppv에 있으므로, 해당 값을 넘겨주는 것**으로 CoGetClassObject() 함수 역할은 종료된다.