Вы находитесь на странице: 1из 228

2- ,

........................................................................................................................................................................9
........................................................................................................................................................................11
............................................................................................................................................11
, Windows !...........................................................11
C++...................................................................................................................................................................................12
++ .................................................................................................................................................12
..........................................................................................................................................................................12
Tangram .....................................................................................................................................13
....................................................................................................................................13
?...................................................................................................................................13
.............................................................................................................................................14
1
...............................................................................................................................................................15
........................................................................................................16
.............................................................................................................................................16
..........................................................................................................................................16
....................................................................................................................................17
.......................................................................................................................................17
.........................................................................................................................................17
..............................................................................................................................................................17
COM.................................................................................................................................................................................19
......................................................................................................................................19
.........................................................................................................................................................20
........................................................................................................................................................20
.................................................................................................................................................................20
, .........................................................................................................................20
..........................................................................................................21
2
....................................................................................................................................................................23
................................................................................................................................................23
..............................................................................................23
...............................................................................................................24
....................................................................................................................................24
........................................................................................................................................25
...................................................................................................................................................26
....................................................................................................................28
.....................................................................................................................................................28
, II .....................................................................................................................................29
.....................................................................................................................................30
..............................................................................................................................................................30
.....................................................................................................................................................30
.................................................................................................................................30
vtbl ........................................................................................................................31
....................................................................................................................................32
, vtbl................................................................................................................................32
, .............................................................................................................................................34

4
3
QUERYINTERFACE........................................................................................................................................................ 35
....................................................................................................................................................... 36
IUnknown ..................................................................................................................................................................... 36
IUnknown ........................................................................................................................... 36
QueryInterface..................................................................................................................................... 37
QueryInterface ................................................................................................................................... 37
QueryInterface ......................................................................................................................................... 37
.................................................................................................................................................. 40
QUERYINTERFACE................................................................................................................... 43
IUnknown ..................................................................................................... 44
, ....................................................... 44
, ..................................................................... 44
, .............................................................................................. 45
- -, ................ 45
QUERYINTERFACE ................................................................................................................... 46
......................................................................................... 46
............................................................................................................... 46
.................................................................................................................... 47
....................................................................................................................................... 48
.................................................................................................................................................. 48
? ........................................................................................................................................................ 48
4
...................................................................................................................................................... 51
..................................................................................................................................... 51
............................................................................................................................................................ 52
........................................................................................................... 53
AddRef Release ..................................................................................................................................... 54
..................................................................................................................................... 59
................................................................................................................................ 59
......................................................................................................................................... 61
, .................................................................................................................................. 62
5
.......................................................................................................................... 65
................................................................................................................................................. 65
DLL .......................................................................................................................................... 65
DLL............................................................................................................................................................... 67
..................................................................................................................................................... 68
....................................................................................................................................................... 69
........................................................................................................................................................... 72
, ................................................................................................................................... 73
6
HRESULT, GUID, .................................................................................................... 75
HRESULT........................................................................................................................................................................ 75
HRESULT ......................................................................................................................................................... 77
HRESULT .......................................................................................................................................... 78
................................................................................................................ 79
GUID................................................................................................................................................................................ 80
GUID? .................................................................................................................................................. 80
GUID .............................................................................................................................. 81
GUID......................................................................................................................................................... 82
GUID ...................................................................... 82
GUID ......................................................................................................................................... 82
WINDOWS ............................................................................................................................................................ 82
................................................................................................................................................ 82
..................................................................................................................................................... 82
.............................................................................................................................................. 83

5
.............................................................................................................................................83
ProgID..........................................................................................................................................................................84
.......................................................................................................................................................85
...........................................................................................................................................86
OleView ........................................................................................................................................................................87
COM .....................................................................................................................87
COM .............................................................................................................................87
.................................................................................................................................................88
GUID .................................................................................................................................88
............................................................................................................................................................................89
7
.......................................................................................................................................................91
COCREATEINSTANCE ..........................................................................................................................................................91
CoCreateInstance .....................................................................................................................................91
CoCreateInstance...............................................................................................................................92
........................................................................................................................................................92
...............................................................................................................................................93
CoCreateInstance ...............................................................................................................94
............................................................................................................................................................94
CoGetClassObject ..............................................................................................................................95
IClassFactory ...............................................................................................................................................................95
CoCreateInstance vs. CoGetClassObject.....................................................................................................................96
........................................................................................96
.......................................................................................................................................97
DllGetClassObject..............................................................................................................................97
...........................................................................................................................................................97
........................................................................................................................................98
...........................................................................................................................103
........................................................................................................................................103
DLL ...................................................................................................................104
............................................................................................104
DLL ..............................................................................................................................................................105
DllCanUnloadNow...........................................................................................................................105
LockServer..................................................................................................................................................................105
..........................................................................................................................................................................106
8
: ...................107
....................................................................................................................................108
..................................................................................................................................................................108
...........................................................................................................................................................108
...................................................................................................................109
.............................................................................................................................................109
........................................................................................................................................111
......................................................................................................................................112
QueryInterface................................................................................................................................................113
IUnknown..................................................................................................................................................114
IUnknown ............................................................................................................115
........................................................................................................................117
...................................................119
..................................................................................................................................................121
...............................................................................................................................................131
......................................................................................................133
......................................................................................133
...................................................................................................................134
..........................................................................................................................................................................135
9
.............................................................................................................................................................137
........................................................................................................................137

6
Smart- ............................................................................................................................ 137
- C++ ............................................................................................................................................. 145
.......................................................................................................................... 146
CUnknown ........................................................................................................................................ 146
CFactory ........................................................................................................................................... 149
CUnknown CFactory .................................................................................................................... 152
, ....................................................................................................................................... 156
.......................................................................................................................................................................... 157
10
EXE ........................................................................................................................................................... 159
........................................................................................................................................................ 159
................................................................................................................................... 160
................................................................................................................................................................ 160
DLL / .................................................................................................................................... 161
IDL/MIDL................................................................................................................................................. 161
IDL ............................................................................................................................................................................. 162
IDL ............................................................................................................... 162
MIDL ................................................................................................................................................... 166
............................................................................................................................. 168
................................................................................................................................... 169
...................................................................................................................................................... 169
.............................................................................................................................................. 169
LockServer ........................................................................................................................................... 172
...................................................................................................................................................... 173
DCOMCNFG.EXE? ............................................................................................................................. 174
? ............................................................................................................................................ 174
DCOM ..................................................................................................................................... 175
.......................................................................................................................................................................... 177
11
............................................................................ 179
............................................................................................................................................. 179
......................................................................................................................................... 180
IDispatch, , .................................................................................................... 180
IDISPATCH ......................................................................................................................................... 183
Invoke ................................................................................................................................................... 184
.................................................................................................................................................................... 187
VARIANT ............................................................................................................................................................ 188
BSTR ...................................................................................................................................................... 190
SAFEARRAY.......................................................................................................................................... 190
........................................................................................................................................................ 191
..................................................................................................................................... 191
............................................................................................................................. 193
................................................................................................................................... 194
IDISPATCH ................................................................................................................................................ 194
............................................................................................................................................. 196
................................................................................................................................................................ 196
? ............................................................................................................................ 197
12
............................................................................................................................................... 199
COM........................................................................................................................................... 199
Win32........................................................................................................................................................... 199
............................................................................................................................................................ 200
.......................................................................................................................................................... 200
................................................................................................................................................ 202
................................................................................................................................................... 202
................................................................................................................................... 203
........................................................................................................... 204
.................................................................................................................................. 205

7
....................................................................................................................................................205
.....................................................................................................................206
.............................................................................................................................206
...............................................................................................................211
..............................................................................................................................212
..............................................................................................215
........................................................................................................216
..........................................................................................................................................................................217
13
.............................................................................................................................................219
TANGRAM ..................................................................................................................................................220
Tangram .....................................................................................................................................................220
.....................................................................................................................................220
EXE-..........................................................................................................................................221
TangramModel ......................................................................................................................................221
TangramGdiVisual TangramGLVisual ............................................................................................222
TangramGdiWorld TangramGLWorld ............................................................................................222
.......................................................................................................................................223
IDL....................................................................................................................................................................223
DLLDATA.C .....................................................................................................................................................224
.................................................................................................................................224
AddRef...............................................................................................................................................224
....................................................................................................................................225
......................................................................................................................225
................................................................................................................................226
IEnumXXX ..................................................................................................................................................................227
COM ............................................................................................................228
--! ............................................................................................................................................................................228

,
, (, , ) .
. .
. , , ,
( ). ,
, , . ,
. .
, .
(Nigel Tompson) . ,
COM, . (Nancy Cluts)
, .
, , .
(Kraig Brockshmidt) (Craig Wittenberg)
. ,
.
, ; ,
. Microsoft Press ,
COM, (Eric Stroo) . (Kathleen Atkins)
. .
, , . (Pam Nidaka)
- , (Michael Victor)
, * . (Gary Nelson)
, , ,
. (Shawn Peck)
, ,
.
, , . (Mary
Kirtland), (Mark Kramer), (John Thornson), (Tim Bragg),
(Vinoo Cherian), (Charlie Kindel), (Jerry Noll) (Kirk Goddard).
, Microsoft Developer Studio,
, . (Martin Lovell)
.
, , Microsoft Developer Network. MSDN ,
; (Handan Selamoglu).
, .
, , . ,
(Peter Lancaster) (Paul Schuster), ,
, . , , ! ,
. , , Radio Shack TRS-80.

. .: .

- ,
? , ,
? , ?
? ?
, ?
? ?
COM? OLE ? OLE?
, COM OLE ? Microsoft, ActiveX,
DirectX OLE? Microsoft?
!
: Microsoft, COM (Component Object Model).
COM C++.
COM , ,
, .
COM - API. COM
.
, . COM ,
Microsoft, ActiveX, DirectX OLE. Microsoft
COM .


C++, Win32.
C++, . COM C++
, . ++,
, , , COM,
. , ,
. , ,
, ++.
Microsoft Windows , .
, Windows. UNIX
. Windows ,
Windows-.
Microsoft Foundation Class Library (MFC) . MFC
COM, 12
.

, Windows !
UNIX, Macintosh, Linux, VMS - ,
. , ,
Microsoft Windows, API. COM ,
, - .
. , Windows ,
,
. . Microsoft Macintosh,
Software AG .

12

, .

C++
,
. , Java Python Microsoft Visual Basic.
++.
++.
, . Java Python,
, ++, .

++
++,
. bool, mutable .
smart- (. 9), ,
.
static_cast, const_cast
reinterpret_cast, Microsoft Visual C++.
. ,
CFoo* pI = (CFoo*)this;

:
CFoo* pI = static_cast<CFoo*>this;

- , .

.
, . .
. ,
, ,
, .
:
!"
Microsoft Windows 95 Microsoft Windows NT.
!" , ,
REGISTER.BAT, .
!" Win32 API .
!" MFC .
!" . ,
, ++ Win32 SDK. Visual C++,
Win32 SDK , Visual C++ .
Windows- .
!" , Visual C++ 4.x 5.0.
, .
Microsoft Visual C++ 5.0, .
!" , . Microsoft
Visual C++, cl < >.
!" make- Microsoft Visual C++.
nmake f makefile nmake. make-
.

13

Tangram
, .
, Tangram, . -,
API Win32, GDI, MFC OpenGL. -,
. DLL EXE. Tangram ,
COM , .
, .


MFC , MFC.
- m_. m_SleepyBear, ,
. . , CcozyBear
Cozy Bear. . -1.
-1. MFC

CConnectionPoint

IConnectionPoint

m_

BOOL m_bSleepyBear;

s_

static int s_iBears;

g_

int g_Bears[100];

Windows, , , .
, .
, . -2. ,
, COM, OLE
ActiveX.
-2. ,

int* pCount;

pI

IBear* pIBear;

BOOL bBear;

int iNumberOfBears;

dw

DWORD

DWORD dwBears;

DWORD cRefs;

sz

char szName[] = Fuzzy;

wsz

Unicode

wchar_t wszName[] = LFuzzy;

?
? , ,
. ,
. ,
.
.
. , .
COM OLE .
,
.
OLE. OLE, . , OLE
Inside OLE.

14
, , OLE. ,
, OLE. , , .
. ,
.
, , OLE.
Microsoft , OLE.
Direct3D, API Microsoft .
3D Graphics Programming for Windows 95, ,
. ,
, .
, .
OLE , .
OLE. . ,
, OLE, DirectX ActiveX,
.
, , .
ActiveX, OLE .
, . (
++.)


,
. Microsoft Press World Wide Web :
http://www.microsoft.com/mspress/support/

, ,
Microsoft Press :

Microsoft Press
Attn: Inside COM Editor
One Microsoft Way
Redmond, WA 98052-6399

E-mail
MSPINPUT@MICROSOFT.COM

, , .
, ,
.
Web- Microsoft Developer Network (MSDN), :
http://www.microsoft.com/MSDN/

, MSDN, .
(800) 759-5474.
Microsoft (
) :
http://www.microsoft.com/support/

, , Microsoft Win32 SDK Answer Point.


(800) 936-5800, Priority Developer line.
, Microsoft Visual C++, (206)
635-7007 6 6 (Pacific time).

. ,
,
. ,
, . , .
, ,
.
.
,
. , ,
(. 1-1).

. 1-1 ()
()
, , (. 1-2).
, .
.
.
, ,
.
. ;
, .
. ,
, .
.


B

C
, D

. 1-2 D ,
, , . ,
, . (Component Object
Model) .
Microsoft, ,
. Microsoft
. ActiveX .

16
++. , ,
, , ,
.
, ,
.



.
, .
, .


, ,
. , ,
. ,
.
, ,
.
, vi Emacs. . 1-3, 1
vi, 2 Emacs.
, .
1

vi

Emacs

. 1-3 .
1 vi, 2 Emacs.



. ,
, , (. 1-4).

. 1-4 , ,

.
ActiveX ( OLE).
Visual Basic, C, C++ Java ActiveX

17
Web. , -
, .


,
, .
. -
, , .
, .
-, , . , , ,
. , . 1-5
C D .
, C D.
C D . ,
C D - .
.
.

D
E

2
D

. 1-5
, , ,
. , .



. . , . -, ( )
. , ,
. . ,
, .
.



. , .
.
, , , ,
. ,

. , ,
. , ,
, , . , ,
, -.

, .
, . ,
.

18
, , , .
, ,
, , .
, , .
, , (client).
(interface). ,
. , ,
. , ,
.
, , ,
. .
.
, , .
, .
.
:
1.

.
, ,
.
.

2.

. ,
, ,
.

3.

,
. ,
.

4.

. ,
,
. .
, ,
, .

.

,
. , ,
, Objective C.
, ++.
, ,
++. .
, , EspressoBeans, , ++ .
, EspressoBeans. ,
.
. , Visual Basic.
, Visual Basic, - .
, .
. .

, . ,
, .
, . . 1-6
vi , .
. ,
,
.

19

vi

vi

. 1-6

, .

COM
COM . , .
, ,
. ,
. VHS,
.
, . PCMCIA
. , , .
, .
. Microsoft ,
( , ).
(COM Specification) ,
. , ,
. Microsoft. , , ,
.


,
(DLL) EXE- Win32. , ,
.
. DLL. ,
, .
.
, :
!" .
, Ada, C, Java, Modula-3, Oberon Pascal.
, Smalltalk Visual Basic,
. , .
!" .
!" , . . 3,
.
!" .
, .
. ,
.
- API
. ,
, .
, , ,
.

20


. . ,
++ ; . , .
.
++.
DLL.
. , , DLL.
, DLL, .
DLL . ,
DLL.
, , API , API Win32.
, MoveWindow .. ( ,
, .) , ,
- API. COM ++,
MFC. COM , ,
.


, : .
API; , ,
. API ,
Windows. ,
.
, .
. (Distributed COM,
DCOM) Windows , .
, , .


.
, , .
Windows- .
, Windows.
. - ,
.
.

,
, .
DLL , .
, ,
:
!" , ;
!" ;
!" ;
!" , ;
!" .
.
.
, , .

, .
, (object
linking and embedding). ,

21
, , , .
, Microsoft, OLE. OLE
,
(dynamic data exchange DDE). OLE 1 . DDE
Windows. , OLE 1, , ,
. DDE . DDE . , DDE
. , - .
. , , , DDE. OLE
DDE. ,
OLE. OLE ,
. OLE ,
. , .
, OLE , . OLE
, ,
.
OLE - . ,
, OLE .
, , . OLE
.
Microsoft , .
, . !


,
.
, , .
,
.
. ,
, . ,
. .
. ,
, . ,
. , .


. ,
. , !
, .
,
. ,
. , ,
. , !
(interface).
. ,
.
.
.
DLL , . ++
. , ,
. ,
. .
, .
, .
; , .
, ++.
++ .
,
. ,
.
. .
. , ,
, .


. .
. ,
. , .
. 1 , (
. 2-1). ,
. ,
. . . 2-1
.


, , , .
, . ;
, , -.
.
. , .

24

A-C

C-D
B-D

A-B

B-E

D-E
E

. 2-1 ,
. ,
. , .
, , . ,
, .
.

. ,
, .
.
, . ,
.


, , ,
. -, . ,
-, . ,
, , .
-, .
(polymorphism).
, , , .
.
.
. , .
,
, , .
, ,
- . .


, . CA
IX IY .
class IX
{
public:
virtual void Fx1() = 0;
virtual void Fx2() = 0;
};

//

class IY
{

//

25
public:
virtual void Fy1() = 0;
virtual void Fy2() = 0;
};
class CA : public IX, public IY
//
{
public:
// IX
virtual void Fx1() { cout << Fx1 << endl; }
virtual void Fx2() { cout << Fx2 << endl; }
// IY
virtual void Fy1() { cout << Fy1 << endl; }
virtual void Fy2() { cout << Fy2 << endl; }
};

IX IY , .
(pure abstract base class) ,
(pure virtual functions). ,
=0 (pure specifier).
, . , IX::Fx1, IX::Fx2, IY::Fy1
IY::Fy2 . .
CA IX IY
.
, - IX IY, CA .
, . ++
, .. .
.
, .
, ,
. (public)
(interface inheritance),
. ,
.
.
, ,
. .
, ++ ,
.
IX IY . , IX IY
IUnknown. IUnknown ,
. , IX IY .


, .
I. , IX X.
C, CA A.
,
OBJBASE.H Microsoft Win32 Software Development Kit (SDK):
#define interface struct

struct, class,
, public.
. , .
#include <objbase.h>
interface IX
{
virtual void __stdcall Fx1() = 0;
virtual void __stdcall Fx2() = 0;
};

26
interface IY
{
virtual void __stdcall Fy1() = 0;
virtual void __stdcall Fy2() = 0;
}

,
. . 2-2.

IX
IY

. 2-2
++. ,
(A, B, C++, ).


, IX IY.
++ .
. 5, . 2-1 CA ,
IX IY. main.
IFACE.CPP .
Microsoft Visual C++,
cl iface.cpp

__stdcall ( Pascal)
, __stdcall. ,
Microsoft. ( , -
.) , Win32,
. Borland, Symantec Watcom. ,
__stdcall, Pascal.
. /++
, . , Visual Basic,
.
, Win32 API,
. - ,
__cdecl. Windows , ,
Windows 640 .*
, Microsoft,
.
. , .
. ,
, , ,
.
, , pascal. WINDEF.H
#define pascal __stdcall

, pascal Pascal,
OBJBASE.H:
#define STDMETHODCALLTYPE __stdcall

*
Pascal ( , ..),
, ( , ..). :
, Pascal. . .

27
IFACE.CPP
//
// Iface.cpp
// : cl Iface.cpp
//
#include <iostream.h>
#include <objbase.h>
//
void trace(const char* pMsg) { cout << pMsg << endl; }
//
interface IX
{
virtual void __stdcall Fx1() = 0;
virtual void __stdcall Fx2() = 0;
};
interface IY
{
virtual void __stdcall Fy1() = 0;
virtual void __stdcall Fy2() = 0;
};
//
class CA : public IX,
public IY
{
public:
// IX
virtual void __stdcall Fx1() { cout << "CA::Fx1" << endl; }
virtual void __stdcall Fx2() { cout << "CA::Fx2" << endl; }
// IY
virtual void __stdcall Fy1() { cout << "CA::Fy1" << endl; }
virtual void __stdcall Fy2() { cout << "CA::Fy2" << endl; }
};
//
int main()
{
trace(": ");
CA* pA = new CA;
// IX
IX* pIX = pA;
trace(": IX");
pIX->Fx1();
pIX->Fx2();
// IY
IY* pIY = pA;
trace(": IY");
pIY->Fy1();
pIY->Fy2();
trace(": ");
delete pA;
return 0;
}

2-1
:
:

28
: IX
CA::Fx1
CA::Fx2
: IY
CA::Fy1
CA::Fy2
:

, .
IX IY. CA,
IX, IY. CA - .
. ,
. ++,
.
:
!" ++
!"
!" ++
.

,
. - ,
2-1.


, , ?
2-1 . pA CA,
. , .
CA , , ( ) CA.
. .
( )
. , ,
. , ,
- .
, , .
, ,
. . 3 , CA.
CA.
CA ,
.
new delete. ,
++. . 4 ,
. . 6 7 .

.


2-1 ++. , ,
.
. ,
.

2-1 CA . , ++
. .
. ++
, ++.
, .

29

CA . , , ,
, .
. ,
, .
Inside OLE.
, ;
++ .

.
. 2-1 CA IX IY,
.
.
- (. . 2-3).
, , .

.
. .
1
Fx1
Fx2
IX1
...
Fxn

2
Fx1
Fx2
IX1
...
Fxn

n
Fx1
Fx2
IX1
...
Fxn

Fx1
Fx2
...
Fxn

Fx1
Fx2
...
Fxn

Fx1
Fx2
...
Fxn

IX2

IX2

...

IXn

...

IX2

...

...
Fx1
Fx2
...
Fxn

IXn

Fx1
Fx2
...
Fxn

IXn

Fx1
Fx2
...
Fxn

. 2-3 ,
,


,
. , . ;
.
, .
. . 8.
. ,
, ;
, .
,
. .
, IFly Xyz IXyzFly.
, , .

, II
, .
. : ,
.

30


2-1 , , .
. , ,
. ,
.
. , ,
.
.

, , .
.
,
. , .
. ,
. ,
. ,
. ,
. ,
.
, ,
, , , , , ,
, ? , ,
, . , , ; , .
.
, Viewer (bitmap). ,
, IDisplay. Viewer
. ,
VRML. , Viewer, ,
IDisplay, , VRML. ,
VRML ,
.
.
, .
;
, . ,
,
. , , IDisplay
VRML
, .
, ,
.
, , , , ,
,
.


, ++
. ,
. , ,
.


, .
. . 2-4
, :

31
interface IX
{
virtual
virtual
virtual
virtual
};

void
void
void
void

__stdcall
__stdcall
__stdcall
__stdcall

Fx1()
Fx2()
Fx3()
Fx4()

=
=
=
=

0;
0;
0;
0;

.
, .
, .
IX

pIX

vtbl

&Fx1
&Fx2
&Fx3
&Fx4


-

. 2-4 ,

, , . . 2-4
(virtual function table). , vtbl
. vtbl
Fx1, . Fx2, ..
vtbl, vtbl.
vtbl, , , vtbl.
, ,
++ . ,
. , IX ,
. ,
. , .
, . ++
, . 2-4. .
++
, . ,
, . 2-4. ++ Windows
vtbl, 1.
, ,
. IUnknown,
. , vtbl .
- Iunknown. . 3.

vtbl
vtbl? vtbl
.
.
++ , , ,
vtbl , . , CA
IX, .
class CA : public IX
{
public:

. , Mac vtbl
, .

32
// IX
virtual void __stdcall Fx1()
virtual void __stdcall Fx2()
virtual void __stdcall Fx3()
virtual void __stdcall Fx4()

{
{
{
{

cout
cout
cout
cout

<<
<<
<<
<<

CA::Fx1 << endl; }


m_Fx2 << endl; }
m_Fx3 << endl; }
m_Fx4 << endl; }

//
CA(double d) : m_Fx2(d*d), m_Fx3(d*d*d), m_Fx4(d*d*d*d)
{}
//
double m_Fx2;
double m_Fx3;
double m_Fx4;
};

vtbl CA, , . 2-5. ,


CA. ,
, .
IX

CA

vtbl

&Fx1

Fx1

&m_Fx2

&Fx2

Fx2

&m_Fx3

&Fx3

Fx3

&m_Fx4

&Fx4

Fx4

pA

. 2-5 , ,
vtbl
++ ,
. ,
. , .
, .


vtbl , .
vtbl.
CA, .
vtbl . , , CA:
int main()
{
// CA
CA* pA1 = new CA(1.5);
// CA
CA* pA2 = new CA(2.75);

vtbl,
-. (. 2-6).
, vtbl vtbl.
vtbl.

, vtbl
, , ,
. , CB,
IX:
class CB : public IX
{
public:

33
// IX
virtual void __stdcall Fx1()
virtual void __stdcall Fx2()
virtual void __stdcall Fx3()
virtual void __stdcall Fx4()

{
{
{
{

cout
cout
cout
cout

<<
<<
<<
<<

CB::Fx1
CB::Fx2
CB::Fx3
CB::Fx4

<<
<<
<<
<<

endl;
endl;
endl;
endl;

}
}
}
}

};
vtbl

CA

&m_Fx3

&Fx1

Fx1

&m_Fx4

&Fx2

Fx2

vtbl

&Fx3

Fx3

&m_Fx2

&Fx4

Fx4

&m_Fx2

pA1
pA2

&m_Fx3
&m_Fx4

. 2-6 vtbl
IX CA, CB:
void foo(IX* pIX)
{
pIX->Fx1();
pIX->Fx2();
}
int main ()
{
// CA
CA* pA = new CA(1.789);
// CB
CB* pB = new CB;
// IX CA
IX* pIX = pA;
foo(pIX);
// IX CB
pIX = pB;
foo(pIX);

CA, CB , IX.
. . 2-7 .
, - , .
vtbl

pA

pB

vtbl

CA

&Fx1

Fx1

&Fx2

Fx2

&Fx3

Fx3

&Fx4

Fx4

CB

&Fx1

Fx1

&Fx2

Fx2

&Fx3

Fx3

&Fx4

Fx4

. 2-7

34
. 2-7 , CA CB , vtbl
. vtbl ,
. Fx1 , Fx2 , ..
, .
, .
. IX, ,
.

,
.
,
. , ,
. , .
, , .
, , ++ .
, ++ ,
.
, , .
. ,
. vtbl .
QueryInterface. ,
!

3
QueryInterface
?
>
?
>
?
>
?
>
?
>

, ,
(Animal). , ;
- . ,
.
Animal , ,
. , , ,
, . ,
. ,
. .
, Animal. Animal ,
; , . ,
,
. , Animal
. , Animal ,
, .
Logo. Logo
Animal. , - .
Animal, ,
. ,
.
. ,
. ,
, . , , ,
, Animal .
Animal ,
. ,
, . , ,
. ,
, .
, , .
, .
, , ,
, .
, ,
. ,
.

36


, ,
.
.
IUnknown. IUnknown,
UNKNWN.H, Win32 SDK, :
interface IUnknown
{
virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) = 0;
virtual ULONG __stdcall AddRef() = 0;
virtual ULONG __stdcall Release() = 0;
}

IUnknown QueryInterface. , ,
. QueryInterface. . 4
AddRef Release, .

IUnknown
IUnknown. ,
, *. .
IUnknown. , IUnknown, ,
, , ,
.

IX

CA

pA

vtbl

QueryInterface

QueryInterface

AddRef

AddRef

Release

Release

Fx

Fx

. 3-1 IUnknown
QueryInterface, AddRef Release
vtbl
IUnknown, QueryInterface, AddRef
Release vtbl (. . 3-1).
IUnknown. vtbl
, . IUnknown,
QueryInterface. ,
, .
IUnknown,
. .

IUnknown
IUnknown?
CreateInstance, IUnknown:
IUnknown* CreateInstance();

CreateInstance new.
,
. . 6 7 .
, , IUnknown, ,
QueryInterface , QueryInterface.

Unknown (.) . . .

37

QueryInterface
IUnknown - QueryInterface, ,
. QueryInterface , ;
(
).
QueryInterface :
Virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);

, IID-. IID
. 6. , .
, QueryInterface .
QueryInterface HRESULT; (handle), . HRESULT
32- , . QueryInterface
S_OK, E_NOINTERFACE. QueryInterface
; SUCCEEDED FAILED.
HRESULT . 6.
, , QueryInterface.

QueryInterface
, IUnknown, pI. ,
, QueryInterface, .
QueryInterface , :
void foo(IUnknown* pI)
{
//
IX* pIX = NULL;
// IX
HRESULT hr = pI->QueryInterface(IID_IX, (void**)&pIX);
//
if (SUCCEEDED(hr))
{
//
pIX->Fx();
}
}

pI , IID_IX.
IID_IX , (, ,
, . 13).
, pIX NULL QueryInterface.
. , ,
QueryInterface NULL. , QueryInterface
, .
NULL .
QueryInterface.
. , QueryInterface .

QueryInterface
QueryInterface . , , ,
IID. , S_OK .
E_NOINTERFACE NULL. QueryInterface
, CA:
interface IX : IUnknown { /*...*/ };
interface IY : IUnknown { /*...*/ };
class CA : public IX, public IY { /*...*/ };

. 3-2.

38
IUnknown

IUnknown

IX

IY
CA

. 3-2

, IUnknown . IX IY IUnknown
, vtbl, . IX
IY IUnknown , vtbl
- IUnknown.
QueryInterface .
IUnknown, IX IY. ,
IUnknown , CA
( IX IY).
HRESULT __stdcall CA::QueryInterface(const IID& iid, void** ppv)
{
if (iid == IID_IUnknown)
{
*ppv = static_cast<IX*>(this);
}
else if (iid == IID_IX)
{
// IX
*ppv = static_cast<IX*>(this);
}
else if (iid = IID_IY)
{
// IY
*ppv = static_cast<IY*>(this);
}
else
{
// .
// NULL.
*ppv = NULL;
return E_NOINTERFACE;
}
static_cast<IUnknown*>(*ppv)->AddRef(); // . . 4
return S_OK;
}

QueryInterface if-then-else.
, . ,
- ; , . , ,
case*, , .
, QueryInterface NULL,
. , ; NULL
, . ,
, . , AddRef
QueryInterface . AddRef . 4.

, , , QueryInterface this, ppv.
. , , ppv, . -,
this IX , IY. :

*
case Pascal. ++ switch,
case . . .

39
static_cast<IX*>(this) != static_cast<IY*>(this)
static_cast<void*>(this) != static_cast<IY*>(this)

, , ,
(IX*)this != (IY*)this
(void*)this != (IY*)this

this , ++
. .
, void, this .
IUnknown. :
*ppv = static_cast<IUnknown*>(this);

//

, IUnknown , IX IY. ,
, static_cast<IUnknown*>(static_cast<IX*>(this))

static_cast<IUnknown*>(static_cast<IY*>(this)) . ,
. ,
, IUnknown .
.

.
++ .
++ . , ++ CA:
class CA : public IX, public IY { ... }

CA IX, IY, CA ,
IX IY. CA , IX IY,
. :
void foo(IX* pIX);
void bar(IY* pIY);
int main()
{
CA* pA = new CA;
foo(pA);
bar(pA);
delete pA;
return 0;
}

foo IX, bar


IY. IX IY, ,
. bar vtbl IX , . ,
foo, bar,
CA , . . 3-3
CA .
CA::this
(IX*)CA::this
(IY*)CA::this

IX vtbl
IY vtbl

CA

IY

QueryInterface
AddRef
Release

IX

Fx

CA

QueryInterface
AddRef
Release

IY

Fx

. 3-3 CA, IX IY

40
. 3-3 , this CA IX.
, CA this IX.
, this CA vtbl IY. , this CA
, , IY.
this CA vtbl IY (IY). :
IY* pC = pA;

-
IY* pC = (char*)pA + IY;

Multiple Inheritance and Casting


. (Margaret A. Ellis) (Bjarne Strourstrup) The Annotated C++ Reference Manual.
++ vtbl ,
. 3-3.


QueryInterface.
3-1 .
. .
IX, IY IZ. IUnknown
UNKNWN.H Win32 SDK.
. CA , IX
IY. QueryInterface , .
CreateInstance CA. , ,
CA, IUnknown .
CreateInstance IID . , IID
( . 7).
UUID.LIB, IID_IUnknown (.. IID IUnknown).
main, .
IUNKNOWN.CPP
//
// IUnknown.cpp
// : cl IUnknown.cpp UUID.lib
//
#include <iostream.h>
#include <objbase.h>
void trace(const char* msg) { cout << msg << endl; }
//
interface IX : IUnknown
{
virtual void __stdcall Fx() = 0;
};
interface IY : IUnknown
{
virtual void __stdcall Fy() = 0;
};
interface IZ : IUnknown
{
virtual void __stdcall Fz() = 0;
};
// GUID
extern const IID IID_IX;
extern const IID IID_IY;
extern const IID IID_IZ;

41
//
//
//
class CA : public IX, public IY
{
// IUnknown
virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);
virtual ULONG __stdcall AddRef() { return 0; }
virtual ULONG __stdcall Release() { return 0; }
// IX
virtual void __stdcall Fx() { cout << "Fx" << endl; }
// IY
virtual void __stdcall Fy() { cout << "Fy" << endl; }
};
HRESULT __stdcall CA::QueryInterface(const IID& iid, void** ppv)
{
if (iid == IID_IUnknown)
{
trace("QueryInterface: IUnknown");
*ppv = static_cast<IX*>(this);
}
else if (iid == IID_IX)
{
trace("QueryInterface: IX");
*ppv = static_cast<IX*>(this);
}
else if (iid == IID_IY)
{
trace("QueryInterface: IY");
*ppv = static_cast<IY*>(this);
}
else
{
trace("QueryInterface: ");
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef(); // . . 4
return S_OK;
}
//
//
//
IUnknown* CreateInstance()
{
IUnknown* pI = static_cast<IX*>(new CA);
pI->AddRef();
return pI;
}
//
// IID
//
// {32bb8320-b41b-11cf-a6bb-0080c7b2d682}
static const IID IID_IX =
{0x32bb8320, 0xb41b, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
// {32bb8321-b41b-11cf-a6bb-0080c7b2d682}
static const IID IID_IY =
{0x32bb8321, 0xb41b, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
// {32bb8322-b41b-11cf-a6bb-0080c7b2d682}
static const IID IID_IZ =
{0x32bb8322, 0xb41b, 0x11cf,

42
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
//
//
//
int main()
{
HRESULT hr;
trace(": IUnknown");
IUnknown* pIUnknown = CreateInstance();
trace(": IX");
IX* pIX = NULL;
hr = pIUnknown->QueryInterface(IID_IX, (void**)&pIX);
if (SUCCEEDED(hr))
{
trace(": IX ");
pIX->Fx();
// IX
}
trace(": IY");
IY* pIY = NULL;
hr = pIUnknown->QueryInterface(IID_IY, (void**)&pIY);
if (SUCCEEDED(hr))
{
trace(": IY ");
pIY->Fy();
// IY
}
trace(": ");
IZ* pIZ = NULL;
hr = pIUnknown->QueryInterface(IID_IZ, (void**)&pIZ);
if (SUCCEEDED(hr))
{
trace(": IZ ");
pIZ->Fz();
}
else
{
trace(": IZ");
}
trace(": IY IX");
IY* pIYfromIX = NULL;
hr = pIX->QueryInterface(IID_IY, (void**)&pIYfromIX);
if (SUCCEEDED(hr))
{
trace(": IY ");
pIYfromIX->Fy();
}
trace(": IUnknown IY");
IUnknown* pIUnknownFromIY = NULL;
hr = pIY->QueryInterface(IID_IUnknown, (void**)&pIUnknownFromIY);
if (SUCCEEDED(hr))
{
cout << " IUnknown? ";
if (pIUnknownFromIY == pIUnknown)
{
cout << ", pIUnknownFromIY == pIUnknown" << endl;
}
else
{
cout << ", pIUnknownFromIY != pIUnknown" << endl;

43
}
}
//
delete pIUnknown;
return 0;
}

3-1 QueryInterface
:
: IUnknown
: IX
QueryInterface: IX
: IX
Fx
: IY
QueryInterface: IY
: IY
Fy
:
QueryInterface:
: IZ
: IY IX
QueryInterface: IY
: IY
Fy
: IUnknown IY
QueryInterface: IUnknown
IUnknown? , pIUnknownFromIY == pIUnknown

CreateInstance. CreateInstance
IUnknown . QueryInterface IUnknown
IX . SUCCEEDED.
IX , Fx.
IUnknown, IY.
. CA IX, IY, QueryInterface
. CA IZ.
, QueryInterface E_NOINTERFACE. SUCCEEDED
FALSE, pIZ ( - IZ).
- . IY
IX, pIX. IY, ,
IY , .
, IUnknown IY.
IUnknown, . ,
IUnknown, pIUnknownFromIY, IUnknown, pIUnknown.
, : QueryInterface
IUnknown.
, QueryInterface CA
. QueryInterface.
.

QueryInterface
, QueryInterface.
, , ()
. QueryInterface ,
.
!" IUnknown.
!" , .
!" , .

44
!" , .
!" - -, .
.

IUnknown
IUnknown. ,
IUnknown ( , ), .
, , IUnknown
. SameComponents , pIX pIY
:
BOOL SameComponents(IX* pIX, IY* pIY)
{
IUnknown* pI1 = NULL;
IUnknown* pI2 = NULL;
// IUnknown pIX
pIX->QueryInterface(IID_IUnknown, (void**)&pI1);
// IUnknown pIY
pIY->QueryInterface(IID_IUnknown, (void**)&pI2);
//
return pI1 == pI2;
}

. ,
.

,
QueryInterface ,
. ,
QueryInterface .
. .
, , .
. ?
? , , ?
-
.

,
IX, IX
IX. :
void f(IX* pIX)
{
IX* pIX2 = NULL;
// IX IX
HRESULT hr = pIX->QueryInterface(IID_IX, (void**)&pIX2);
assert(SUCCEEDED(hr)); //
}

. , ? , ,
IUnknown IUnknown.
IUnknown
. :
void f(IUnknown* pI)
{
HRESULT hr;
IX* pIX = NULL;
// IX pI

45
hr = pI->QueryInterface(IID_IX, (void**)&pIX);
// -
}
void main()
{
// - IX
IX* pIX = GetIX();
//
f(pIX);
}

f IX , IX.

,
IX IY,
IX IY. , ,
, , . :
void f(IX* pIX)
{
HRESULT hr;
IX* pIX2 = NULL;
IY* pIY = NULL;
// IY IX
hr = pIX->QueryInterface(IID_IY, (void**)&pIY);
if (SUCCEEDED(hr))
{
// IX IY
hr = pIY->QueryInterface(IID_IX, (void**)&pIX2);
// QueryInterface
assert(SUCCEEDED(hr));
}
}

- -,

,
, . IY IX, IZ IY, IZ
IX. :
void f(IX* pIX)
{
HRESULT hr;
IY* pIY = NULL;
// IY IX
hr = pIX->QueryInterface(IID_IY, (void**)&pIY);
if (SUCCEEDED(hr))
{
IZ* pIZ = NULL;
// IZ IY
hr = pIY->QueryInterface(IID_IZ, (void**)&pIZ);
if (SUCCEEDED(hr))
{
// IZ IX
hr = pIX->QueryInterface(IID_IZ, (void**)&pIZ);
//
assert(SUCCEEDED(hr));
}
}
}

QueryInterface . , ,
, .

46
, , .
.
QueryInterface , ,
. , QueryInterface
. QueryInterface ,
. , , QueryInterface
. , QueryInterface.

QueryInterface
QueryInterface , . ,
, , QueryInterface.
QueryInterface, ++, .
++.
QueryInterface.
QueryInterface , , .
, , .
++,
. ,
. , , .
++.
; , . (
Animal).


, , :
?. : ,
? , ( ).
, .
, IX IY,
IY. , . IX
IY. IY, .
- ,
. .
, , .
, .
, (type libraries), ,
, .
, - , ,
. . . 11.
,
. , ,
, . ,
(component category).
, .
, ; . 6.
QueryInterface
.


, . , , . , ,
? (IID). ,
, IID. QueryInterface
IID, . QueryInterface IID,
. QueryInterface IID .

47
QueryMultipleInterfaces
(DCOM) ImultiQI. QueryMultipleInterfaces.
. QueryMultipleInterfaces -
, .
, , IID, .
. , .
, ,
, .
.
, , .
, . .
, . .
, , Pilot,
. ,
Pilot, - IFly.
, Bronco IFly.
Pilot , FastPilot. FastPilot
IFastFly, IFly. , Bronco, IFastFly
FastBronco.
FastPilot - IFly, , Bronco, FastPilot . FastPilot IFlyFast,
, IFly. FastBronco - IFly, -
Pilot, FastBronco . . 3-4 .
Pilot

Bronco

pIFly

IFly

FastPilot

FastBronco

pIFly

IFly

pIFlyFast

IFlyFast

. 3-4
.
,
. .
, IID . , ,
, IID.


, ,
IID. IID,
:
!" ;
!" ;
!" ;
!" ;
!" ;
!" ;
!" ;

48
!" .
, , ,
. (, , , .)


, .
. , IFly IFly2, IFastFly.
, .
- , ,
.


,
.
. ,
, .
.
. , , ,
. -, ,
, . ,
.
. ,
- . . ,
, , .
, ,
. ,
. , , Foo1, Foo2 Foo3 .
, Foo3, ,
.
. ,
, .
, . ,
-.
. ,
, , .
.

?
, . QueryInterface ,
++. QueryInterface
. QueryInterface ,
, .
, QueryInterface
. QueryInterface
.
.
IUnknown , .
QueryInterface , IUnknown. ,
-, AddRef Release, delete (
). , , Animal?
?
>
?
>
AddRef?
>
?
> Release

49
AddRef?
>

4

. ,
. - . , , -,
, (- ,
). -, - : ,
, . . ,
, . ,
, . .
++ . ,
, , .
. , ++.
, .
: ? ?
?
, -. ,
. , ?,
, ,
. ? .
( -,
).

. , ,
.
.


, . ,
-.
.
IUseOxygen,
IUseAxe. IUseAxe , IUseOxygen.
, , .
, , , ,
.
IUnknown . , ,
, .
. .
, : , ,
, . ,
, (), . , ,
, .
,
.
- IUnknown AddRef Release.
IUnknown, :
interface IUnknown
{
virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) = 0;

52
virtual ULONG __stdcall AddRef() = 0;
virtual ULONG __stdcall Release() = 0;
};

, AddRef Release
, . ,
, AddRef Release. ,
. , , AddRef Release
.


AddRef Release , (reference counting).
, .
. ,
. , .
, . ,
. , , ,
AddRef, Release.
, , :
1.

AddRef . , ,
AddRef . QueryInterface
CreateInstance. , AddRef
( ) .

2.

Release. ,
Release.

3.

AddRef .
, AddRef. : ,
.

. .
.
IX. AddRef, CreateInstance QueryInterface.
Release IUnknown, CreateInstance, IX,
QueryInterface.
//
IUnknown* pIUnknown = CreateInstance();
// IX
IX* pIX = NULL;
HRESULT hr = pIUnknown->QueryInterface(IID_IX, (void**)&pIX);
if (SUCCEEDED(hr))
{
pIX->Fx();
// IX
pIX->Release();
// IX
}
pIUnknown->Release();// IUnknown

IUnknown
QueryInterface, .
//
IUnknown* pIUnknown = CreateInstance();
// IX
IX* pIX = NULL;
HRESULT hr = pIUnknown->QueryInterface(IID_IX, (void**)&pIX);
// IUnknown
pIUnknown->Release();
// IX,
if (SUCCEEDED(hr))
{
pIX->Fx();
// IX

53
pIX->Release();

// IX

, , , .
IX.
, ,
3.
//
IUnknown* pIUnknown = CreateInstance();
IX* pIX = NULL;
HRESULT hr = pIUnknown->QueryInterface(IID_IX, (void**)&pIX);
pIUnknown->Release();
if (SUCCEEDED(hr))
{
pIX->Fx();
// IX
IX* pIX2 = pIX;
// pIX
pIX2->AddRef();
//
pIX2->Fx();

// - pIX2

pIX2->Release();
pIX->Release();

// pIX2
// pIX

:
AddRef Release pIX2? ,
AddRef Release? .
. AddRef Release pIX2 . , ,
, pIX2 , pIX2
pIX. .
AddRef ,
. , , AddRef Release
. , ,
, , .
, . 10, smart- .
: ,
QueryInterface. , QueryInterface AddRef .
, Release.
, , 0. ,
.


. , ,
. ? ,
. , , .
, , (.
. 4-1), .
, .
, , .
, .

IUnknown

IUnknown

IX

IX

IY

IY

. 4-1

54
? ,
AddRef , , -
. Release , .
, :
IUnknown* pIUnknown = CreateInstance();
IX* pIX = NULL;
pIUnknown->QueryInterface(IID_IX, (void**)&pIX);
pIX->Fx();
IX* pIX2 = pIX;
pIUnknown->AddRef();

// pIX2->AddRef();

pIX2->Fx();
pIX2->Release();
pIUnknown->Release();// pIX->Release();
pIUnknown->Release();

, AddRef Release IUnknown,


IX. .
,
? :
.

, Release ; .
, delete ,
. , , ;
. , .
.
,
. .

.
QueryInterface , . ,
, , ,
. .
, ,
. , (aggregation),
. 8.
, .
, .

AddRef Release
AddRef ( Release) .
() , .
ULONG __stdcall AddRef()
{
return ++m_cRef;
}
ULONG __stdcall Release()
{
if (--m_cRef == 0)
{
delete this;
return 0;
}
return m_cRef;
}

55
AddRef m_cRef, . Release m_cRef
, .
AddRef Release Win32 InterlockedIncrement InterlockedDecrement.
,
. , ,
. , , . 12.
ULONG __stdcall AddRef()
{
return InterlockedIncrement(&m_cRef);
}
ULONG __stdcall Release()
{
if (InterlockedDecrement(&m_cRef) == 0)
{
delete this;
return 0;
}
return m_cRef;
}

, AddRef Release
. , -
.
. 3, , AddRef
QueryInterface CreateInstance.
HRESULT __stdcall CA::QueryInterface(const IID& iid, void** ppv)
{
if (iid == IID_IUnknown)
{
*ppv = static_cast<IX*>(this);
}
else if (iid == IID_IX)
{
*ppv = static_cast<IX*>(this);
}
else if (iid == IID_IY)
{
*ppv = static_cast<IY*>(this);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
static_cast<IUnknown*>(*ppv)->AddRef(); // . . 4
return S_OK;
}
IUnknown* CreateInstance()
{
IUnknown* pI = static_cast<IX*>(new CA);
pI->AddRef();
return pI;
}

, , . ,
, .
, CreateInstance QueryInterface AddRef.
AddRef Release . ,
, 4-1, .
.

56
REFCOUNT.CPP
//
// RefCount.cpp
// : cl RefCount.cpp UUID.lib
//
#include <iostream.h>
#include <objbase.h>
void trace(const char* msg) { cout << msg << endl; }
// GUID
extern const IID IID_IX;
extern const IID IID_IY;
extern const IID IID_IZ;
//
interface IX : IUnknown
{
virtual void __stdcall Fx() = 0;
};
interface IY : IUnknown
{
virtual void __stdcall Fy() = 0;
};
interface IZ : IUnknown
{
virtual void __stdcall Fz() = 0;
};

//
//
//
class CA : public IX, public IY
{
// IUnknown
virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
// IX
virtual void __stdcall Fx() { cout << "Fx" << endl; }
// IY
virtual void __stdcall Fy() { cout << "Fy" << endl; }
public:
//
CA() : m_cRef(0) {}
//
~CA() { trace("CA: "); }
private:
long m_cRef;
};
HRESULT __stdcall CA::QueryInterface(const IID& iid, void** ppv)
{
if (iid == IID_IUnknown)
{
trace("CA QI: IUnknown");
*ppv = static_cast<IX*>(this);
}
else if (iid == IID_IX)
{
trace("CA QI: IX");

57
*ppv = static_cast<IX*>(this);
}
else if (iid == IID_IY)
{
trace("CA QI: IY");
*ppv = static_cast<IY*>(this);
}
else
{
trace("CA QI: ");
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
return S_OK;
}
ULONG __stdcall CA::AddRef()
{
cout << "CA: AddRef = " << m_cRef+1 << endl;
return InterlockedIncrement(&m_cRef);
}
ULONG __stdcall CA::Release()
{
cout << "CA: Release = " << m_cRef-1 << endl;
if (InterlockedDecrement(&m_cRef) == 0)
{
delete this;
return 0;
}
return m_cRef;
}
//
//
//
IUnknown* CreateInstance()
{
IUnknown* pI = static_cast<IX*>(new CA);
pI->AddRef();
return pI;
}
//
// IID
//
// {32bb8320-b41b-11cf-a6bb-0080c7b2d682}
static const IID IID_IX =
{0x32bb8320, 0xb41b, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
// {32bb8321-b41b-11cf-a6bb-0080c7b2d682}
static const IID IID_IY =
{0x32bb8321, 0xb41b, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
// {32bb8322-b41b-11cf-a6bb-0080c7b2d682}
static const IID IID_IZ =
{0x32bb8322, 0xb41b, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
//
//
//
int main()
{
HRESULT hr;

58
trace(": IUnknown");
IUnknown* pIUnknown = CreateInstance();
trace(": IX");
IX* pIX = NULL;
hr = pIUnknown->QueryInterface(IID_IX, (void**)&pIX);
if (SUCCEEDED(hr))
{
trace(": IX ");
pIX->Fx();
// IX
pIX->Release();
}
trace(": IY");
IY* pIY = NULL;
hr = pIUnknown->QueryInterface(IID_IY, (void**)&pIY);
if (SUCCEEDED(hr))
{
trace(": IY ");
pIY->Fy();
// IY
pIY->Release();
}
trace(": ");
IZ* pIZ = NULL;
hr = pIUnknown->QueryInterface(IID_IZ, (void**)&pIZ);
if (SUCCEEDED(hr))
{
trace(": IZ ");
pIZ->Fz();
pIZ->Release();
}
else
{
trace(": IZ");
}
trace(": IUnknown");
pIUnknown->Release();
return 0;
}

4-1
:
: IUnknown
CA: AddRef = 1
: IX
CA QI: IX
CA: AddRef = 2
: IX
Fx
CA: Release = 1
: IY
CA QI: IY
CA: AddRef = 2
: IY
Fy
CA: Release = 1
:
CA QI:

59
: IZ
: IUnknown
CA: Release = 0
CA:

, . 3, .
AddRef Release. Release,
. ,
delete. AddRef,
CreateInstance QueryInterface.


, . ,
AddRef/Release, .
, .


,
. , :
HRESULT hr;
IUnknown* pIUnknown = CreateInstance();
IX* pIX = NULL;
hr = pIUnknown->QueryInterface(IID_IX, (void**)&pIX);
pIUnknown->Release();
if (SUCCEEDED(hr))
{
IX* pIX2 = pIX;
// pIX
// pIX2 pIX
pIX2->AddRef();
//
pIX->Fx();
// IX
pIX2->Fx();
// - pIX2
pIX2->Release();
// pIX2
pIX->Release();
// IX
//
}

, pIX.
pIX , pIX, pIX2.
, pIX,
pIX2. , AddRef Release pIX2,
, , .
pIX , . ,
pIX2 pIX. ,
, pIX2. . 4-2 pIX pIX2
.
. . ,
, . ,
.
. 4-2 , pIX2 pIX
pIX. , pIX pIX2.
pIX2 pIX, , pIX2
. , pIX2 pIX :
HRESULT hr;
IUnknown* pIUnknown = CreateInstance();
IX* pIX = NULL;
hr = pIUnknown->QueryInterface(IID_IX, (void**)&pIX);
pIUnknown->Release();
if (SUCCEEDED(hr))
{
IX* pIX2 = pIX;
// pIX
pIX2->AddRef();
// pIX2

60
pIX->Fx();
pIX->Release();
pIX2->Fx();
pIX2->Release();

// IX
// pIX2
//

IUnknown

pIX

pIX2

CreateInstance

QueryInterface

pIUnknown->Release()

pIX2 = pIX
pIX2->AddRef()

pIX2->Release()
pIX->Release()

. 4-2 .
.
AddRef pIX2, pIX2 pIX.
. 4-3.

IUnknown

pIX

pIX2

CreateInstance

QueryInterface

pIUnknown->Release()

pIX2 = pIX
pIX2->AddRef()

pIX->Release()
pIX2->Release()

. 4-3 .
.
, .
, .
, - . .
, foo pIX. ,
AddRef Release .
void foo(IX* pIX2)
{
pIX2->Fx();
}

// IX

void main()
{
HRESULT hr;
IUnknown* pIUnknown = CreateInstance();
IX* pIX = NULL;
hr = pIUnknown->QueryInterface(IID_IX, (void**)&pIX);
pIUnknown->Release();
if (SUCCEEDED(hr))

61
{
foo(pIX);
pIX->Release();

// pIX
// IX
//

}
}

,
. , ..
.

.
,
. .
, , ,
AddRef / Release .


,
. , , ,
. ,
, .

(out parameter) ,
. ; ,
. , .
QueryInterface.
HRESULT QueryInterface(const IID&, void**);

,
, AddRef . ,
AddRef , -. QueryInterface
, AddRef .
CreateInstance .

(in parameter) , .
, .
++ .
:
void foo(IX* pIX)
{
pIX->Fx();
}

, , AddRef Release,
. ,
.
:
IX* pIX = CreateInstance();
foo(IX);
pIX->Release();

// AddRef

foo :
IX* pIX = CreateInstance();
// foo(pIX);
pIX->Fx();
pIX->Release();

// AddRef
// foo

foo , .

62
-
- (in-out parameter) , .
, .
Release , ,
.
AddRef .
void ExchangeForChangedPtr(int i, IX** ppIX)
{
(**ppIX)->Fx();
// -
(**ppIX)->Release();
//
*ppIX = g_Cache[i];
(**ppIX)->AddRef();
(**ppIX)->Fx();

//
// AddRef
// -


, ,
AddRef / Release. .
pIX2 foo.
, pIX, ,
AddRef Release pIX2 .
void foo(IX* pIX)
{
IX* pIX2 = pIX;
pIX2->Fx();
}


,
, AddRef. ,
Release . , , . -
.

, , AddRef / Release.
,
, . ,
, . ,
, . ,
, , ,
. , ,
.
Release , AddRef. ++
Release , , delete Release. . 10 ,
smart- .

,
IUnknown . ,
, , QueryInterface. ,
AddRef Release . AddRef ,
. Release , . Release
.
; Release ,
. , .
,
.

63
.
.

5

? ,
. -
, !
. ,
IUnknown, .
, .
QueryInterface
. , ,
. .
, , ,
. , IUnknown, ,
. , .
DLL. ,
DLL. DLL,
. DLL , . ,
DLL. DLL , .
, , ,
DLL. 4-1 . 4
. , ,
. ?
, .
DLL, .
, ( ).
, .


, . ,
. ; ,
.
, DLL
. . 3 CreateInstance
IUnknown. DLL, .
. ,
CreateInstance, .

DLL
DLL .
(C linkage), extern C. , CreateInstance
CMPNT1.CPP :
//
//
//
extern C IUnknown* CreateInstance()
{
IUnknown* pI = (IUnknown*)(void*)new CA;
PI->AddRef();

66
return pI;
}

extern C , ++
. extern C Microsoft Visual C++ 5.0 CreateInstance
?CreateInstance@@YAPAUIUnknown@@XZ

.
, . , .

Microsoft Visual C++, DUMPBIN.EXE
, DLL.
dumpbin exports Cmpnt1.dll

CMPNT1.DLL :
Microsoft (R) COFF Binary File Dumper Version 4.20.6281
Copyright (C) Microsoft Corp 1992-1996. All rights reserved.
Dump of file Cmpnt1.dll
File Type: DLL
Section contains the following Exports for Cmpnt1.dll
0 characteristics
325556C5 time date stamp Fri Oct 04 11:26:13 1996
0.00 version
1 ordinal base
1 number of functions
1 number of names
ordinal hint name
1

CreateInstance

(00001028)

Summary
7000 .data
1000 .idata
3000 .rdata
2000 .reloc
10000 .text

, , extern C.
, . DEF. DEF
, ; ,
. - .
DEF . . DEF
CMPNT1.DLL 5-1.
CMPNT1.DEF
;
; Cmpnt1
;

LIBRARY

Cmpnt1.dll

DESCRIPTION

(c)1996-1997 Dale E. Rogerson

EXPORTS
CreateInstance @1 PRIVATE

5-1 ,

67
, , EXPORTS .
(ordinal number). LIBRARY
DLL.
DLL. , DLL .

DLL
CREATE.H CREATE.CPP CreateInstance. CreateInstance DLL
, DLL CreateInstance.
5-2.
CREATE.CPP
//
// Create.cpp
//
#include <iostream.h>
#include <unknwn.h>

// IUnknown

#include "Create.h"
typedef IUnknown* (*CREATEFUNCPTR)();
IUnknown* CallCreateInstance(char* name)
{
//
HINSTANCE hComponent = ::LoadLibrary(name);
if (hComponent == NULL)
{
cout << "CallCreateInstance:\t: "
<< endl;
return NULL;
}
// CreateInstance
CREATEFUNCPTR CreateInstance
= (CREATEFUNCPTR)::GetProcAddress(hComponent, "CreateInstance");
if (CreateInstance == NULL)
{
cout << "CallCreateInstance:\t: "
<< " CreateInstance"
<< endl;
return NULL;
}
return CreateInstance();
}

5-2 LoadLibrary GetProcAddress,



DLL CreateInstance Win32 LoadLibrary:
HINSTANCE LoadLibrary(
LPCTSTR lpLibFileName
);

// DLL

LoadLibrary DLL DLL.


Win32 GetProcAddress (CreateInstance), :
FARPROC GetProcAddress(
HMODULE hModule,
LPCSTR lpProcName
}

// DLL
//

DLL
CreateInstance. , IUnknown .
CallCreateInstance , , ,
, CreateInstance.

68
CallCreateInstance .
DLL, .
DLL .
DLL
DLL ? , DLL
, .
, .
. vtbl
. vtbl, .
, vtbl. Windows
vtbl, , .
Windows . (EXE)
, 4 .
.
, .
, , 369 . ,
. , .
. ,
.

DLL 1

DLL 3

DLL 2

DLL 2

, ,
. DLL, EXE ,
. DLL (in-proc server).
. 10 (out-of-proc), ,
EXE-. ,
, - DLL
. . 5-1 DLL
.

DLL 4

. 5-1 ,
,
, , , ,
, . ,
. ,
, . ,
, , ,
EXE . ,
, .
. 6 7 , .
. 7 CoCreateInstance CallCreateInstance, CallCreateInstance
.


, . : ,
? , -
. , 4-1
, . CHAP05
. .
. 5-2 , .

69

CLIENT1.CPP
CREATE.H
CREATE.CPP

IFACE.H
GUIDS.CPP

CMPNT1.CPP
CMPNT1.DEF

. 5-2
CLIENT1.CPP. CREATE.H
CLIENT1.CPP. , DLL. ( CREATE.CPP
5-2.) . 7 , ,
.
CMPNT1.CPP.
, , DLL. CMPNT1.DEF,
5-1.
. IFACE.H ,
CMPNT1. .
GUIDS.CPP (, GUID ).
:
cl Client.cpp Create.cpp GUIDS.cpp UUID.lib
cl /LD Cmpnt1.cpp GUIDS.cpp UUID.lib Cmpnt1.def

, , make-. ,
? , make-, . ,
, , ,
. , , :
nmake f makefile

.
( ).


, , -
. , , 5-3.
DLL. CallCreateInstance, DLL
CreateInstance.
CLIENT1.CPP
//
// Client1.cpp
// : cl Client1.cpp Create.cpp GUIDs.cpp UUID.lib
//
#include <iostream.h>
#include <objbase.h>
#include "Iface.h"
#include "Create.h"
void trace(const char* msg) { cout << " 1:\t" << msg << endl; }
//
// 1
//
int main()
{
HRESULT hr;
//

70
char
cout
cin
cout

name[40];
<< " [Cmpnt?.dll]: ";
>> name;
<< endl;

// CreateInstance DLL
trace(" IUnknown");
IUnknown* pIUnknown = CallCreateInstance(name);
if (pIUnknown == NULL)
{
trace(" CallCreateInstance ");
return 1;
}
trace(" IX");
IX* pIX;
hr = pIUnknown->QueryInterface(IID_IX, (void**)&pIX);
if (SUCCEEDED(hr))
{
trace("IX ");
pIX->Fx();
// IX
pIX->Release();
}
else
{
trace(" IX");
}
trace(" IUnknown");
pIUnknown->Release();
return 0;
}

5-3 DLL, . DLL,


.
5-4 . extern C CreateInstance,
.
CMPNT1.CPP. CMPNT1.CPP /LD. ,
CMPNT1.DEF, 5-1.
CMPNT1.CPP
//
// Cmpnt1.cpp
// : cl /LD Cmpnt1.cpp GUIDs.cpp UUID.lib Cmpnt1.def
//
#include <iostream.h>
#include <objbase.h>
#include "Iface.h"
void trace(const char* msg) { cout << " 1:\t" << msg << endl; }
//
//
//
class CA : public IX
{
// IUnknown
virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
// IX
virtual void __stdcall Fx() { cout << "Fx" << endl; }
public:

71
//
CA() : m_cRef(0) {}
//
~CA() { trace(" "); }
private:
long m_cRef;
};
HRESULT __stdcall CA::QueryInterface(const IID& iid, void** ppv)
{
if (iid == IID_IUnknown)
{
trace(" IUnknown");
*ppv = static_cast<IX*>(this);
}
else if (iid == IID_IX)
{
trace(" IX");
*ppv = static_cast<IX*>(this);
}
else
{
trace(" ");
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
return S_OK;
}
ULONG __stdcall CA::AddRef()
{
return InterlockedIncrement(&m_cRef);
}
ULONG __stdcall CA::Release()
{
if (InterlockedDecrement(&m_cRef) == 0)
{
delete this;
return 0;
}
return m_cRef;
}
//
//
//
extern "C" IUnknown* CreateInstance()
{
IUnknown* pI = static_cast<IX*>(new CA);
pI->AddRef();
return pI;
}

5-4 , ,
. 4.
IFACE.H GUIDS.CPP. IFACE.H
, .
IFACE.H
//
// Iface.h
//
//
interface IX : IUnknown

72
{
virtual void __stdcall Fx() = 0;
};
interface IY : IUnknown
{
virtual void __stdcall Fy() = 0;
};
interface IZ : IUnknown
{
virtual void __stdcall Fz() = 0;
};
// GUIDs
extern "C"
{
extern const IID IID_IX;
extern const IID IID_IY;
extern const IID IID_IZ;
}

5-5
, - IX, IY IZ.
IFACE.H. IID .
GUIDS.CPP, 5-6.
GUIDS.CPP
//
// GUIDs.cpp
//
#include <objbase.h>
extern "C"
{
// {32bb8320-b41b-11cf-a6bb-0080c7b2d682}
extern const IID IID_IX =
{0x32bb8320, 0xb41b, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
// {32bb8321-b41b-11cf-a6bb-0080c7b2d682}
extern const IID IID_IY =
{0x32bb8321, 0xb41b, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
// {32bb8322-b41b-11cf-a6bb-0080c7b2d682}
extern const IID IID_IZ =
{0x32bb8322, 0xb41b, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
// extern , C++
}

5-6 GUIDS.CPP.
, .
DLL. .


, .
CHAP05 ; 1, 2 3.
, 1, 2 3. IFACE.H
: IX, IY IZ. 1 1 IX. 2 2
IX IY. 3 3 . . 5-1
, .

73
5-1 ,

IX

IY

IZ
1
2
#


nmake f makefile

, .
<Enter>. .
. , .
.
, . ,
, . 2
2 3 1.
C:\client2
[Cmpnt?.dll]: cmpnt2.dll
2:

2:

2:
Fx
2:

2:
Fy
2:

2:
2:

2:

2:

IUnknown
IUnknown
IX
IX
IX
IY
IY
IY
IUnknown

C:\client3
[Cmpnt?.dll]: cmpnt1.dll
3:
3:

3:
Fx
3:

3:
3:

3:
3:

1:

1:
1:
1:

IUnknown
IX
IX
IX
IY

IY
IZ

IZ
IUnknown

2 , 2. 1 IX,
3 : IX, IY IZ. .
? -, . ,
. ,
, .

,
.
DLL, . ,
.

, .

74
, - , ,
. CallCreateInstance , DLL, .
DLL , .
DLL, , .
DLL . .

6
HRESULT, GUID,

.
. ,
.
. FAA* ,
49% . 51% - .
51% , , 250 5000 .
, ,
, . ,
, . .
, , ,
, , , , , , , ,
, , , , ,
.
, ,
. , ,
, .
, .
, . ,
.
HRESULT , . 3 QueryInterface.
GUID. GUID IID, QueryInterface.
, (
).
.

HRESULT
, .
( Windows NT),
- . , , .
, .
, ,
. ,
( ) . .
.
HRESULT. QueryInterface HRESULT. , ,
HRESULT. HRESULT
, (handle) , . HRESULT 32-
, . , HRESULT, . 6-1.
; (heres the result),
(handle of result).

Federal Aviation Agency, . . .

76
HRESULT Win32 WINERROR.H.
Win32, , HRESULT.
HRESULT Win32, , .
HRESULT, . 6-1, , .
, . 16
. 15 .

15

16

31 30

16 15

. 6-1 HRESULT
. 6-1 .
S_, E_.
6-1 HRESULT

S_OK

.
, .
S_OK 0

NOERROR

, S_OK

S_FALSE

.
S_FALSE 1

E_UNEXPECTED

E_NOIMPL

E_NOINTERFACE

.
QueryInterface

E_OUTOFMEMORY

E_FAIL

, S_FALSE 1, S_OK 0.
/++, 0 , -0 . HRESULT
S_FALSE S_OK.
30- 16- (facility). ,
. Microsoft,
. ,
, . 6-2.
6-2 ,
FACILITY_WINDOWS

FACILITY_STORAGE

FACILITY_SSPI

FACILITY_RPC

FACILITY_Win32

FACILITY_CONTROL

10

FACILITY_NULL

FACILITY_ITF

FACILITY_DISPATCH

FACILITY_CERT

11

77
, , Microsoft, RPC (FACILITY_RPC),
,
ActiveX (FACILITY_CONTROL). ,
.
.
, FACILITY_ITF, .
. FACILITY_ITF ; ,
. HRESULT,
HRESULT_FACILITY, WINERROR.H.
, FACILITY_ITF
, . ,
HRESULT.

HRESULT
, ( OLE , ActiveX),
, WINERROR.H. ;
E_NOINTERFACE :
// MessageID: E_NOINTERFACE
//
// MessageText:
//
// *
//
#define E_NOINTERFACE
0x80004002L

HRESULT FACILITY_WIN32, .
Win32, HRESULT. ,
Win32, 16 . , ,
0x80070103. 7 FACILITY_WIN32. WINERROR.H
, HRESULT. 16
; 259,
Win32.
// MessageID: ERROR_NO_MORE_ITEMS
//
// MessageText:
//
//
//
#define ERROR_NO_MORE_ITEMS
259L

HRESULT WINERROR.H , .
, HRESULT,
. ( ActiveX, OLE, Win32)
API Win32 FormatMessage:
void ErrorMessage(LPCTSTR str, HRESULT hr)
{
void* pMsgBuf;
::FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
hr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&pMsgBuf,
0,
NULL
);
//
cout << str << \r\n;
cout << Error ( << hex << hr << ): << (LPTSTR)pMsgBuf << endl;

WINERROR , , -. . .

78
//
LocalFree(pMsgBuf);
}

HRESULT
, HRESULT , .
:
!" , ;
!" , .

, ,
. SUCCEEDED FAILED.
HRESULT - , S_OK;
HRESULT - , E_FAIL.
, :
HRESULT hr = CreateInstance(...);
if (hr == E_FAIL)
// !
return;
hr = pI->QueryInterface(...);
if (hr == S_OK)
// !
{
pIX->Fx();
pIX->Release();
}
pI->Release();

SUCCEEDED FAILED.
HRESULT hr = CreateInstance(...);
if (FAILED(hr))
return;
hr = pI->QueryInterface(...);
if (SUCCEEDED(hr))
{
pIX->Fx();
pIX->Release();
}
pI->Release();


, , HRESULT,
. , , ,
. , .
, .
, .
,
. , E_UNEXPECTED.
.
. . ,
, ,
, .
, .
HRESULT
.
, . ,
, ,
. , ,
HRESULT. , :

79
double GetCordLength(double BladeSection);

HRESULT, :
HRESULT GetCordLength(/* in */ double BladeSection, /* out */ double* pLength);

HRESULT , .
( OLE ) .
. 10.


, S_OK E_UNEXPECTED.
, . HRESULT,
, FACILITY_ITF.
, .
, FACILITY_ITF,
, 216 .
.
FACILITY_ITF. ,
. ,
, HRESULT
. GUID
, GUID . , FACILITY_ITF
,
(IID).
, , .
, , , , .
.
E_UNEXPECTED. , ,
.
, , .
, , IX::Fx, IY::Fy.
IY::Fy HRESULT FACILITY_ITF, IX::Fx .
IX , HRESULT IX, IY. , IX::Fx
IY HRESULT FACILITY_ITF ,
. IX , E_UNEXPECTED.
IX , .
HRESULT:
!" 0x0000 0x01FF.
FACILITY_ITF, .
!" FACILITY_ITF .
!" , .
!" HRESULT;
.
, HRESULT,
MAKE_HRESULT. ,
MAKE_HRESULT HRESULT. :
MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 512);
MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_ITF, 513);

.
,
AIRPLANE_E_LANDINGWITHGEARUP
HELICOPTER_S_ROTORRPMGREEN

HRESULT . GUID.

80

GUID
FAA N- (N number),
, .
. GUID,
.
. 3 IID , . ,
IID_IX, IID :
extern const IID IID_IX =
{0x32bb8320, 0xb41b, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};

IID , 128 (16 )


GUID. GUID Globally Unique IDentifier ( ;
geoduck1 druid).

GUID?
GUID, (long integer)?
232 . , .
, , ,
. ,
QueryInterface . ,
.
, , ?
- N- ,
FAA, .
; , -
, FAA, , .
GUID . GUID , -
. Microsoft Visual C++ GUID
UUIDGEN.EXE VC++, GUIDGEN.EXE.
UUIDGEN.EXE, , GUID:
{166769E1-88E8-11CF-A6BB-0080C7B2D692}

UUIDGEN GUID. UUIDGEN ,


GUID, . ( ) , ,
UUIDGEN, GUID.
GUIDGEN.EXE Microsoft Visual C++.
, : Microsoft CoCreateGuid,
RPC UuidCreate.
GUID
GUID .
GUID 48- , ,
. . ,
GUID, , ,
. , ,
. GUID 60 .
100- , 00:00:00:00 15 1582 .
GUID 3400 .
( , , ,
3400 ; , Windows 2000.)
GUID Open Software Foundation (OSF); , UUID
(Universally Unique IDentifiers ). UUID
(DCE, Distributed Computing Environment).
(RPC) DCE UUID , ..
, .

gooey duck. GUI duck.

81
UUID GUID CAE Specification X/Open DCE: Remote
Procedure Call.

GUID
GUID (128 ), , . .
5 GUID GUIDS.CPP :
extern const IID IID_IX =
{0x32bb8320, 0xb41b, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};

IFACE.H :
extern C const IID IID_IX;

GUID , , .
GUID , DEFINE_GUID,
OBJBASE.H. DEFINE_GUID GUID GUIDGEN.EXE.
GUID .
.
// {32bb8320-b41b-11cf-a6bb-0080c7b2d682}
DEFINE_GUID(<<name>>,
{0x32bb8320, 0xb41b, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};

GUID . <<name>> ,
, , IID_IX:
// {32bb8320-b41b-11cf-a6bb-0080c7b2d682}
DEFINE_GUID(IID_IX,
{0x32bb8320, 0xb41b, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};

OBJBASE, DEFINE_GUID - :
extern C const GUID IID_IX;

, OBJBASE.H INITGUID.H, DEFINE_GUID


:
extern C const IID IID_IX =
{0x32bb8320, 0xb41b, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};

. 6-2. IFACE.H
DEFINE_GUID IID_IX. IID_IX GUIDS.H.
, INITGUID.H OBJBASE.H IFACE.H. ,
CMPNT.CPP IID_IX , INITGUID.H
.
, DEFINE_GUID ,
GUID.
GUIDS.CPP
#include <objbase.h>
#include <initguid.h>
#include "Iface.h"

IID_IX ,
INITGUID.H

IFACE.H
DEFINE_GUID(IID_IX,
0x32bb8320, 0xb41b, 0x11cf,
0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82);

CMPNT.CPP
#include <objbase.h>
#include "Iface.h"
( )

IID_IX ,
INITGUID.H

. 6-2 INITGUID.H DEFINE_GUID GUID

82

GUID
GUID OBJBASE.H operator==:
inline BOOL operator ==(const GUID& guid1, const GUID& guid2)
{
return !memcmp(&guid1, &guid2, sizeof(GUID));
}

QueryInterface.
, OBJBASE.H
IsEqualGUID, IsEqualIID IsEqualCLSID.

GUID
, GUID
. . 5 CallCreateInstance.
DLL, :
IUnknown* CallCreateInstance(char* name);

CoCreateInstance.
, GUID. GUID
. IID, CLSID.

GUID
GUID 16 , , .
QueryInterface .
const IID&

REFID.
REFCLSID, GUID REFGUID.
, (
).

Windows
FAA , . ,
. - , , DLL
.
. 5 CallCreateInstance DLL.
CallCreateInstance CoCreateInstance.
CoCreateInstance CLSID (
DLL). , CLSID, Windows.
CoCreateInstance , CLSID .
, . Windows
.
, . Windows
; .
, , .


. (key).
, /
(default value). , , .
, .
. 6-3.


. , .
, Windows-,

83
. REGEDT32.EXE Windows NT REGEDIT.EXE Windows 95*.
: , , .

. 6-3 Windows


: HKEY_CLASSES_ROOT.
HKEY_CLASSES_ROOT CLSID. CLSID ,
. CLSID {xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx}. CLSID .
CLSID .
CLSID InprocServer32.
DLL. InprocServer32 , DLL
(in-proc); . . 6-4
CLSID .
, HKEY_CLASSES_ROOT\CLSID CLSID Tail Rotor
Simulator. CLSID .
InprocServer32 DLL C:\Helicopter\TailRotor.dll.
CLSID .
. .


HKEY_CLASSES_ROOT. CLSID,
, .
HKEY_CLASSES_ROOT ,
. . ProgID
(program identifier). ProgID
. ProgID, , CLSID.
GUID , , . .
!" AppID APPID (application identifier
) . DCOM . 10.

Windows NT 4.0 REGEDIT.EXE . .

84
!" Component Categories CATID (component category ID
) . .
!" Interface IID , .
.
. 10.
!" Licenses Licenses .
.
!" TypeLib , . LIBID , .
. 11.

HKEY_CLASSES_ROOT

CLSID

{00000300-0000-0000-C000-000000000046}

StdOleLink

InprocServer32

ole32.dll

{166769E1-88E8-11CF-A6BB-0080C7B2D682}
InprocServer32

Tail Rotor Simulator

C:\Helicopter\TailRotor.dll

. 6-4 CLSID

ProgID
ProgID . HKEY_CLASSES_ROOT
ProgID. ProgID , CLSID.
, Visual Basic, ProgID, CLSID.
ProgID , .
ProgID . ( , ,
GUID.)
ProgID
ProgID :
<>.<>.<>

:
Visio.Application.3
Visio.Drawing.4
RealAudio.ReadAudio ActiveX Control (32-bit).1
Office.Binder.95
MSDEV.APPLICATION
JuiceComponent.RareCat.1

, , ,
.
, . ,
ProgID, . ProgID
. ProgID
. ProgID, , MSDEV.APPLICATION.

85
ProgID
ProgID ProgID CLSID.
ProgID CLSID. CLSID ProgID
. ProgID HKEY_CLASSES_ROOT.
ProgID ,
ProgID . ProgID CLSID,
CLSID . ProgID
HKEY_CLASSES_ROOT. CurVer,
ProgID .
. 6-5 . 6-4, ProgID. CLSID
ProgID, Helicopter.TailRotor.1 ProgID .
ProgID VersionIndependentProgID.
ProgID Helicopter.TailRotor.
HKEY_CLASSES_ROOT
CLSID

{166769E1-88E8-11CF-A6BB-0080C7B2D682}
InprocServer32

C:\Helicopter\TailRotor.dll

ProgID

ProgID

Helicopter.TailRotor.1

VesionIndependentProgID

Helicopter.TailRotor
CLSID

{166769E1-88E8-11CF-A6BB-0080C7B2D682}
Helicopter.TailRotor.1

Helicopter.TailRotor.1
CLSID

Helicopter.TailRotor

CurVer

ProgID


{166769E1-88E8-11CF-A6BB-0080C7B2D682}

. 6-5 , , ProgID
Helicopter.TailRotor Helicopter.TailRotor.1,
HKEY_CLASSES_ROOT. Helicopter.TailRotor.1
CLSID, CLSID . ProgID Helicopter.TailRotor
CLSID CurVer. CurVer ProgID ,
Helicopter.TailRotor.1.
ProgID CLSID
, , CLSID ProgID .
CLSIDFromProgID ProgIDFromCLSID,
:
CLSID clsid;
CLSIDFromProgID(Helicopter.TailRotor, &clsid);

Windows? DLL
, . , DLL ,
:
STDAPI DllRegisterServer();
STDAPI DllUnregisterServer();

STDAPI OBJBASE.H

86
#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE


extern C HRESULT __stdcall

REGSVR32.EXE .
, , .
make- REGSVR32.EXE .
DllRegisterServer .
DLL LoadLibrary, GetProcAddress , ,
.
DllRegisterServer
DllRegisterServer . Win32 ,
.
:
RegOpenKeyEx
RegCreateKeyEx
RegSetValueEx
RegEnumKeyEx
RegDeleteKey
RegCloseKey

, .
, WINREG.H WINDOWS.H
ADVAPI32.LIB. REGISTRY.H
REGISTRY.CPP , .


Windows , CLSID,
. CLSID .
, ?
.
, , , , .
, ,
. - , ,
.
(component categories).
, CLSID, CATID. ,
, .
, ,
.
.
, ,
. .
++. ,
; ,
. ,
, . ,
, .
.
, ; .
, .
, .
. ,
(graphic engine).

87

,
. Windows (Component
Category Manager), . (CLSID_StdComponentCategoryMgr)
, , ICatRegister ICatInformation. ICatRegister
.
. ICatInformation .
:
!" , ;
!" , ;
!" , .
.
ICatRegister ICatInformation ACTIVEX.MVB.
.
, .
, , ,
. , ,
. README , ,
, .
, ,
, - .

OleView
, .
, ,
.
, . ,
, CLSID.
Win32 SDK OleView .
CLSID GUID OleView ,
. , OleView , .
OleView .
. OleView , , ,
.

COM
.
, .
OLE32.DLL. OLE32.LIB.
.

COM
-, . CoInitialize
, ( CoBuildVersion,
). ,
CoUninitialize. :
HRESULT CoInitialize(void* reserved);
void CoUninitialize();

// NULL

.
CoInitialize , CoUninitialize.
CoInitilialize , S_OK, S_FALSE.
,
,
. EXE, DLL.

88
OleInitialize
OLE, , , ,
, ActiveX, ActiveX. OLE
. ,
OleInitialize OleUninitialize CoInitialize CoUninitialize. Ole*
. Ole* Com*. Ole*
Com* , .
CoInitializeEx
Windows, DCOM, CoInitializeEx,
(free-threaded).
CoInitializeEx . 12.


,
. ? ,
, ,
.
.
(task memory allocator) .
, . ,
, .
, . Imalloc
CoGetMalloc. IMalloc::Alloc , IMalloc::Free ,
IMalloc::Alloc. CoGetMalloc
,
.
CoTaskMemAlloc CoTaskMemFree:
void* CoTaskMemAlloc(
ULONG cb
//
};
void CoTaskMemFree(
void* pv
};

//

, ,
( CoTaskMemFree).

GUID
CLSID.
CLSID . .
StringFromGUID2 GUID :
wchar_t szCLSID[39];
int r = ::StringFromGRUID2(CLSID_Component1, szCLSID, 39);

StringFromGUID2 Unicode, .. wchar_t,


char. , Unicode, char.
ANSI wcstombs, .
#ifndef _UNICODE
// Unicode
char szCLSID_single[39];
wcstombs(szCLSID_single, szCLSID, 39);
#endif

, :

StringFromCLSID

CLSID

89

StringFromIID

IID

StringFromGUID2

GUID ;
,

CLSIDFromString


CLSID

IIDFromString


IID

:
wchar_t* string;
// CLSID
::StringFromCLSID(CLSID_Component1, &string);
//
...
//
::CoTaskMemFree(string);

(, ) , ,
.
. , HRESULT
. GUID , ,
, . ,
GUID , (CLSID)
(IID).
, CLSID Windows.
REGSVR32.EXE DllRegisterServer,
DLL . CLSID
.
, CLSID. ,
.

, C C++; ,
.
OBJBASE.H, BASETYPS.H. :
interface IX : IUnknown
{
virtual void __stdcall Fx() = 0;
};

:
DECLARE_INTERFACE(IX, IUnknown)
{
// IUnknown
STDMETHOD(QueryInterface) (THIS_ REFID, PPVOID) PURE;
STDMETHOD_(ULONG, AddRef) (THIS) PURE;
STDMETHOD_(ULONG, Release) (THIS) PURE;
// IX
STDMETHOD_(void, Fx) (THIS) PURE;
}

, , ,
++. , ,
. , IDL, .
10 11.

,
Lego. ,
. (
). , ,
Lego .
, (3D-printers),
. , ,
. .
.
, .
.
.
1x3, .
Lego, , .
, Lego,
. ,
, 50000 .

,
CoCreateInstance. , .
, .
CoCreateInstance ,
. ,
. , , Lego ,
, .

CoCreateInstance
CoCreateInstance, , CLSID,
.
CoCreateInstance , .
.

CoCreateInstance
CoCreateInstance :
HRESULT __stdcall CoCreateInstance(
const CLSID& clsid,
IUnknown* pUnknownOuter,
DWORD dwClsContext,
const IID& iid,
void** ppv
);

//
//

(in) (out). CLSID


.
. dwClsContext ,
. .

92
, iid IID , .
ppv. CoCreateInstance
IID, QueryInterface .

CoCreateInstance
CoCreateInstance , QueryInterface:
//
IX* pIX = NULL;
HRESULT hr = ::CoCreateInstance(
CLSID_Component1,
NULL,
CLSCTX_INPROC_SERVER,
IID_IX,
(void**)&pIX
);
if (SUCCEEDED(hr))
{
pIX->Fx();
pIX->Release();
};

, CLSID_Component1. ,
NULL. ,
NULL. CLSCTX_INPROC_SERVER CoCreateInstance
, DLL.
, CoCreateInstance , ,
QueryInterface. IID_IX, IX,
pIX. CoCreateInstance , IX .
IX , ,
.


CoCreateInstance dwClsContext ,
: , , .
, :
CLSCTX_INPROC_SERVER
,
. DLL.
CLSCTX_INPROC_HANDLER

.
,
.
.

CLSCTX_LOCAL_SERVER

,
, .
EXE, . 10.

CLSCTX_REMOTE_SERVER

, .
DCOM.
. 10.

: , .
,
. ,
, , .
, . OBJBASE.H
, ( )
(. . 7-1).
CLSCTX_REMOTE_SERVER CLSCTX_ALL CLSCTX_SERVER,
OBJBASE.H _WIN32_WINNT 0x0400.
( OBJBASE.H _WIN32_DCOM.)
: CoCreateInstance CLSCTX_REMOTE_SERVER
, DCOM, CoCreateInstance E_INVALIDARG.

93
, _WIN32_WINNT, 0x0400,
Microsoft Windows NT 3.51 Microsoft Windows 95,
DCOM. CLSCTX_LOCAL_SERVER CLSCTX_REMOTE_SERVER . 10.
7-1

CLSCTX_INPROC

CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER

CLSCTX_ALL

CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER |
CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER

CLSCTX_SERVER

CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER |
CLSCTX_REMOTE_SERVER


.
. 7-1 .
. 5 CoCreateInstance.
CoInitialize CoUninitialize
( . 6).
CLIENT.CPP
//
// Client.cpp
//
#include <iostream.h>
#include <objbase.h>
#include "Iface.h"
void trace(const char* msg) { cout << ": \t\t" << msg << endl; }
//
// main
//
int main()
{
// COM
CoInitialize(NULL);
trace(" CoCreateInstance ");
trace(" IX");
IX* pIX = NULL;
HRESULT hr = ::CoCreateInstance(CLSID_Component1,
NULL,
CLSCTX_INPROC_SERVER,
IID_IX,
(void**)&pIX);
if (SUCCEEDED(hr))
{
trace("IX ");
pIX->Fx();
// IX
trace(" IY");
IY* pIY = NULL;
hr = pIX->QueryInterface(IID_IY, (void**)&pIY);
if (SUCCEEDED(hr))
{
trace("IY ");
pIY->Fy();
// IY
pIY->Release();
trace(" IY");
}
else
{
trace(" IY");
}

94
trace(" IZ");
IZ* pIZ = NULL;
hr = pIX->QueryInterface(IID_IZ, (void**)&pIZ);
if (SUCCEEDED(hr))
{
trace(" IZ ");
pIZ->Fz();
pIZ->Release();
trace(" IZ");
}
else
{
trace(" IZ");
}
trace(" IX");
pIX->Release();
}
else
{
cout << ": \t\t . hr = "
<< hex << hr << endl;
}
// COM
CoUninitialize();
return 0;

7-1

CoCreateInstance
- .
, . -,
. , ,
, , .
, .
, CoCreateInstance CLSID,
. CoCreateInstance .
CoCreateInstance ,
. CoCreateInstance , . ,
, , .
, .
. ,
. , ,
.
, ,
.


CoCreateInstance . ,
(class factory), .
, . ,
, CLSID.
, .
IClassFactory. , CoCreateInstance,
.
, , .
. , ,
IClassFactory, .

95

CoGetClassObject
CoCreateInstance CLSID .
, CLSID , CLSID.
CoGetClassObject.
CoGetClassObject :
HRESULT __stdcall CoGetClassObject(
const CLSID& clsid,
DWORD dwClsContext,
COSERVERINFO* pServerInfo,
const IID& iid,
void** ppv
);

// DCOM

, CoGetClassObject CoCreateInstance.
CLSID . dwClsContext.
. CoGetClassObject ,
CoCreateInstance . .
CoCreateInstance IUnknown, CoGetClassObject COSERVERINFO.
COSERVERINFO DCOM .
. 10.
, CoGetClassObject CoCreateInstance ,
, , .
, CoGetClassObject.
IClassFactory.

IClassFactory
, ,
IClassFactory. :
interface IClassFactory : IUnknown
{
HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter,
const IID& iid,
void** ppv);
HRESULT __stdcall LockServer(BOOL bLock);
}

IClassFactory -, CreateInstance LockServer. LockServer


.
CreateInstance
IClassFactory::CreateInstance . ,
pUnknownOuter IUnknown. ,
CoCreateInstance. .
, QueryInterface.
. .
, - .
CreateInstance , , , .
IClassFactory::CreateInstance CLSID. ,
, CLSID , CoGetClassObject.
IClassFactory2
Microsoft , IClassFactory.
IClassFactory2 IClassFactory .
IClassFactory2 ,
. IClassFactory2 ,
. ,
.

96

CoCreateInstance vs. CoGetClassObject


, IClassFactory
, .
CoCreateInstance, CoGetClassObject. , , CoCreateInstance
CoGetClassObject. , ,
.
HRESULT CoCreateInstance(const CLSID& clsid,
IUnknown* pUnknownOuter,
DWORD dwClsContext,
const IID& iid,
void** ppv)
{
// NULL
*ppv = NULL;
// IClassFactory
IClassFactory* pIFactory = NULL;
HRESULT hr = CoGetClassObject(clsid,
dwClsContext,
NULL,
IID_IClassFactory,
(void**)&pIFactory);
if (SUCCEEDED(hr))
{
//
hr = pIFactory->CreateInstance(pUnknownOuter, iid, ppv);
//
pIFactory->Release();
}
return hr;
}

CoCreateInstance CoGetClassObject IClassFactory .


CoCreateInstance IClassFactory::CreateInstance,
.
CoGetClassObject?
CoGetClassObject CoCreateInstance.
, CoGetClassObject, CoCreateInstance. , CoGetClassObject, ,
IClassFactory. , IClassFactory2, CoGetClassObject. , ,
, , .
CoGetClassObject .
, CoCreateInstance
. , ,
, , .


. ,
. -, ,
CLSID. , CoGetClassObject CLSID,
IClassFactory::CreateInstance . -, CLSID
, . -
DLL, .
CLSID, ,
.
.
.
, , , ,
.

97


,
. , .

DllGetClassObject
. 5 CallCreateInstance CreateInstance DLL.
CoGetClassObject DLL , (
.) DLL . DllGetClassObject. CoGetClassObject
DllGetClassObject, . DllGetClassObject
:
STDAPI DllGetClassObject(
const CLSID& clsid,
const IID& iid,
void** ppv
);

: , CoGetClassObject.
, .
, .
.
, DllGetClassObject CLSID. DLL
, CLSID .


. 7-1.
. -, , CoGetClassObject. , , CoGetClassObject. -, DLL. DLL
DllGetClassObject, CoGetClassObject. DllGetClassObject
. , , ,
.
, , IClassFactory .
IClassFactory::CreateInstance . ,
IClassFactory ,
.

CoGetClassObject

COM
1

CoGetClassObject

IClassFactory

5
pIClassFactory

DllGetClassObject

IClassFactory

IX

8
pIX

IClassFactory::CreateInstance

DLL

IX::Fx

6
IX

. 7-1

.

98


7-2. ++
CFactory. , CFactory .
IUnknown , . CFactory CA
.
, CFactory::CreateInstance DllGetClassObject.
CMPNT.CPP
//
// Cmpnt.cpp
//
#include <iostream.h>
#include <objbase.h>
#include "Iface.h"
#include "Registry.h"

//
//

//
void trace(const char* msg) { cout << msg << endl; }
///////////////////////////////////////////////////////////
//
//
//
static HMODULE g_hModule = NULL; // DLL
static long g_cComponents = 0;
//
static long g_cServerLocks = 0;
//
//
const char g_szFriendlyName[] = "Inside COM, Chapter 7 Example";
// ProgID
const char g_szVerIndProgID[] = "InsideCOM.Chap07";
// ProgID
const char g_szProgID[] = "InsideCOM.Chap07.1";

///////////////////////////////////////////////////////////
//
//
//
class CA : public IX, public IY
{
public:
// IUnknown
virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
// IX
virtual void __stdcall Fx() { cout << "Fx" << endl; }
// IY
virtual void __stdcall Fy() { cout << "Fy" << endl; }
//
CA();
//
~CA();
private:
//
long m_cRef;
};

99
//
//
//
CA::CA() : m_cRef(1)
{
InterlockedIncrement(&g_cComponents);
}
//
//
//
CA::~CA()
{
InterlockedDecrement(&g_cComponents);
trace(":\t\t");
}
//
// IUnknown
//
HRESULT __stdcall CA::QueryInterface(const IID& iid, void** ppv)
{
if (iid == IID_IUnknown)
{
*ppv = static_cast<IX*>(this);
}
else if (iid == IID_IX)
{
*ppv = static_cast<IX*>(this);
trace(":\t\t IX");
}
else if (iid == IID_IY)
{
*ppv = static_cast<IY*>(this);
trace(":\t\t IY");
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
return S_OK;
}
ULONG __stdcall CA::AddRef()
{
return InterlockedIncrement(&m_cRef);
}
ULONG __stdcall CA::Release()
{
if (InterlockedDecrement(&m_cRef) == 0)
{
delete this;
return 0;
}
return m_cRef;
}

///////////////////////////////////////////////////////////
//
//
//
class CFactory : public IClassFactory
{
public:
// IUnknown
virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);

100
virtual ULONG
virtual ULONG

__stdcall AddRef();
__stdcall Release();

// IClassFactory
virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter,
const IID& iid,
void** ppv);
virtual HRESULT __stdcall LockServer(BOOL bLock);
//
CFactory() : m_cRef(1) {}
//
~CFactory() { trace(" :\t\t"); }
private:
long m_cRef;
};
//
// IUnknown
//
HRESULT __stdcall CFactory::QueryInterface(const IID& iid, void** ppv)
{
if ((iid == IID_IUnknown) || (iid == IID_IClassFactory))
{
*ppv = static_cast<IClassFactory*>(this);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
return S_OK;
}
ULONG __stdcall CFactory::AddRef()
{
return InterlockedIncrement(&m_cRef);
}
ULONG __stdcall CFactory::Release()
{
if (InterlockedDecrement(&m_cRef) == 0)
{
delete this;
return 0;
}
return m_cRef;
}
//
// IClassFactory
//
HRESULT __stdcall CFactory::CreateInstance(IUnknown* pUnknownOuter,
const IID& iid,
void** ppv)
{
trace(" :\t\t ");
//
if (pUnknownOuter != NULL)
{
return CLASS_E_NOAGGREGATION;
}
//
CA* pA = new CA;
if (pA == NULL)

101
{
return E_OUTOFMEMORY;
}
//
HRESULT hr = pA->QueryInterface(iid, ppv);
// IUnknown
// ( QueryInterface )
pA->Release();
return hr;
}
// LockServer
HRESULT __stdcall CFactory::LockServer(BOOL bLock)
{
if (bLock)
{
InterlockedIncrement(&g_cServerLocks);
}
else
{
InterlockedDecrement(&g_cServerLocks);
}
return S_OK;
}

///////////////////////////////////////////////////////////
//
//
//
//
// DLL?
//
STDAPI DllCanUnloadNow()
{
if ((g_cComponents == 0) && (g_cServerLocks == 0))
{
return S_OK;
}
else
{
return S_FALSE;
}
}
//
//
//
STDAPI DllGetClassObject(const CLSID& clsid,
const IID& iid,
void** ppv)
{
trace("DllGetClassObject:\t ");
// ?
if (clsid != CLSID_Component1)
{
return CLASS_E_CLASSNOTAVAILABLE;
}
//
CFactory* pFactory = new CFactory;
if (pFactory == NULL)
{
return E_OUTOFMEMORY;
}

//
// 1

102
//
HRESULT hr = pFactory->QueryInterface(iid, ppv);
pFactory->Release();
return hr;
}
//
//
//
STDAPI DllRegisterServer()
{
return RegisterServer(g_hModule,
CLSID_Component1,
g_szFriendlyName,
g_szVerIndProgID,
g_szProgID);
}

//
//
//
STDAPI DllUnregisterServer()
{
return UnregisterServer(CLSID_Component1,
g_szVerIndProgID,
g_szProgID);
}
///////////////////////////////////////////////////////////
//
// DLL
//
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
g_hModule = hModule;
}
return TRUE;
}

7-2 , , DLL
:
:
DllGetClassObject:
:
:
:
:
Fx
:
:
:
Fy
:
:
:
:
:

CoCreateInstance
IX


IX

IX
IX
IY
IY
IY
IZ
IZ
IX

DllGetClassObject . -, ,
, . new
. , DllGetClassObject ,
. IClassFactory::CreateInstance DllGetClassObject.
. IClassFactory::CreateInstance CA,
DllGetClassObject CFactory.

103
, DllGetClassObject ,
IClassFactory::CreateInstance .
. ,
,
. , DllGetClassObject IClassFactory::CreateInstance
, .
DllGetClassObject IClassFactory::CreateInstance . 9.


,
7-1 7-2. . 7-2 .
. , COM, DLL,
. .
, . ,
. , ,
. ,
.

COM
CoCreateInstance

DLL

CoGetClassObject
DllGetClassObject

new CFactory

IClassFactory::CreateInstance(IID_IX)
new CA
IClassFactory::Release

pIX->Fx()

. 7-2 CoCreateInstance
IUnknown .
. CoCreateInstance, . CoCreateInstance
CoGetClassObject. CoGetClassObject .
, CoGetClassObject DLL, . DLL
CoGetClassObject DllGetClassObject. DllGetClassObject DLL-.
, new ++. , DllGetClassObject
IClassFactory, CoCreateInstance.
CreateInstance . IClassFactory::CreateInstance
new. , IX. ,
CoCreateInstance IX .
. .


DLL . DllGetClassObject,
COM .
.
DllRegisterServer DllUnregisterServer Windows
. . 6. REGISTRY.CPP.
, .
REGISTRY.H .
Make-
regsvr32 s Cmpnt.dll

104
CMPNT.DLL. , REGSVR32.EXE
DllRegisterServer, . . .
make-, .
REGISTER.BAT, .
.
DllMain
DLL , DllRegisterServer
DLL. DllMain. C++ main,
. Windows WinMain, DLL DllMain. DllMain
DLL :
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
g_hModule = hModule;
}
return TRUE;
}

g_hModule,
DllRegisterServer DllUnregisterServer.

DLL
, DllGetClassObject DLL.
DllGetClassObject CLSID . CLSID
DllGetClassObject (. . 7-3).

DLL

CoCreateInstance

DllGetClassObject

. 7-3 DLL
, DLL , , DLL
, . DLL,
, . DLL .


, .
CFactory1, CFactory2 CFactory3,
CA, CB CC, .
:
CA* pA = new CA;
pA->QueryInterface(...);

,
.
. new IUnknown.
, CLSID . DllGetClassObject
, .
, , new,
(. . 7-4).

105

CoCreateInstance

DLL
DllGetClassObject

CLSID_1

&CreateFunction_1

CLSID_2

&CreateFunction_2

CLSID_n

&CreateFunction_n

CreateFunction_1

CreateFunction_n

. 7-4
. 9 , .
, .
,
, CLSID. CLSID
. CFactory ,
CFactory


CLSID.
,
IClassFactory::CreateInstance CLSID.

DLL
LockServer DllCanUnloadNow. .
. 5, , DLL .
Win32 LoadLibrary1. DLL,
. .
CoFreeUnusedLibraries, , ,
. .

DllCanUnloadNow
CoFreeUnusedLibraries , DLL
? CoCreateUnusedLibraries DLL, DllCanUnloadNow. DllCanUnloadNow
, DLL - . DLL ,
CoFreeUnusedLibraries . , , DLL
. CMPNT.CPP :
static long g_cComponents = 0;

IClassFactory::CreateInstance g_cComponents,
. DllCanUnloadNow , g_cComponents
0.

LockServer
, DLL ,
. ,
. , , . . 10
, EXE, DLL. ,
. (
.) ,
, , .
. 10. ,
, .
. DLL, ,
. , ,
DLL . IClassFactory,
. DLL ,
IClassFactory . IClassFactory::LockServer

COM CoLoadLibrary, LoadLibrary.

106
. LockServer(TRUE)
LockServer(FALSE) .
LockServer g_cComponents. ,
, .
DllCanUploadNow .

CoCreateInstance.
. CoGetClassObject,
, .
IClassFactory, CoCreateInstance.
, CoCreateInstance CoGetClassObject,
. , .
IClassFactory.
. ( ) IClassFactory
.
Lego , ,
. ,
. - , .
- , ,
. , .

8

:
,
, , ++ .
- :
8-1

++

, . , ,
, . , , ,
- ,
, ,
. , ;
, - .
!
? , . ,
, ,
. . ,
.. .
, ,
. OS/2 Windows, vi
Emacs, Java Python .. , .
,
. ,
, . ++
, .

. , .
++
.
, .. ,
. ,
. , .
.
,
, . -

. , . ,
.

108
. ,
IUnknown .
.


, , , -,
. ,
. . , - ,
. , ,
. ++ .
() (containment)
(aggregation).
, .
(outer component) (inner component) .
, .

++. , ,
. .
. ,
(. 8-1).

IX
IY


IZ

. 8-1
IZ.
, ,
. ,
(. 8-2).

IX
IY


IY

. 8-2
IY.

.
, (
).
. ,
.

109
(. 8-3).
- . ,
, . ,
, .
. ,
QueryInterface.

IX

IY

. 8-3 ,
.
.


. ,
. .
. ,
. , , . ,
, .
. , ,
, , - . . ,
. - ,
. .
, , . ,
, , ,
, , . ,
. , ,
, .
.
, .
, .
, .


, . \CHAP08\CONTAIN
. 1 ;
: IX IY. IY 2 ,
. . 8-2.
, .
,
. .
1, 2.
8-1 1.
, . - m_pIY
IY 2.
CONTAIN\CMPNT1
///////////////////////////////////////////////////////////
//
// 1
//
class CA : public IX, public IY
{

110
public:
// IUnknown
virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);
virtual ULONG
__stdcall AddRef();
virtual ULONG
__stdcall Release();
// IX
virtual void __stdcall Fx() { cout << "Fx" << endl; }
// IY
virtual void __stdcall Fy() { m_pIY->Fy(); }
//
CA();
//
~CA();
// ,
//
HRESULT __stdcall Init();
private:
//
long m_cRef;
// IY
IY* m_pIY;
};

//
//
//
CA::CA() : m_cRef(1), m_pIY(NULL)
{
::InterlockedIncrement(&g_cComponents);
}
//
//
//
CA::~CA()
{
::InterlockedDecrement(&g_cComponents);
trace("");
//
if (m_pIY != NULL)
{
m_pIY->Release();
}
}
//
HRESULT __stdcall CA::Init()
{
trace(" ");
HRESULT hr = ::CoCreateInstance(CLSID_Component2,
NULL,
CLSCTX_INPROC_SERVER,
IID_IY,
(void**)&m_pIY);
if (FAILED(hr))
{
trace(" ");
return E_FAIL;
}
else
{

111
return S_OK;
}
}

8-1 1 IY

, 1. Init
2 , ,
CoCreateInstance. IY ,
, m_pIY.
QueryInterface IUnknown.
, , . 1 IY,
. , , 1
2. :
virtual void Fy() { m_pIY->Fy(); }

1 , Release m_pIY,
2 .
1 .
, CreateInstance 1
Init. 8-2.
CreateInstance CONTAIN\CMPNT1
HRESULT __stdcall CFactory::CreateInstance(IUnknown* pUnknownOuter,
const IID& iid,
void** ppv)
{
//
if (pUnknownOuter != NULL)
{
return CLASS_E_NOAGGREGATION;
}
//
CA* pA = new CA;
if (pA == NULL)
{
return E_OUTOFMEMORY;
}
//
HRESULT hr = pA->Init();
if (FAILED(hr))
{
// .
pA->Release();
return hr;
}
//
hr = pA->QueryInterface(iid, ppv);
pA->Release();
return hr;
}

8-2 Init
, . ,
.



.
. IAirplane (), IFloatPlane
(). :
interface IAirplane : IUnknown

112
{
void TakeOff();
void Fly();
void Land();
};
interface IFloatPlane : IAirplane
{
void LandingSurface(UINT iSurfaceType);
void Float();
void Sink();
void Rust();
void DrainBankAccount();
};

, IAirplane MyAirplane.
MyAirplane IAirplane IAirplane,
IFloatPlane:
void CmyFloatPlane::Fly()
{
m_pIAirplane->Fly();
}

IAirplane, , , :
void CmyFloatPlane::Land()
{
if (m_iLandingSurface == WATER)
{
WaterLanding();
}
else
{
m_pIAirplane->Land();
}
}

, . IAirplane ,
, MyAirplane, . ,
, .
,
. .
.


, . IY. ,
IY, IY,
. IY, - IY,
.
, IY .
, ,
IUnknown .
QueryInterface. QueryInterface ,
.
C++
++ , . ,
++ . ++
(operator ->).
smart- . operator -> ,
. ,
.

113

QueryInterface
, IX IY
.
class CA : public IX
{
public:
// IUnknown
virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
// IX
virtual void __stdcall Fx() { cout << Fx << endl; }
//
CA();
//
~CA();
// ,
//
HRESULT Init();
private:
//
long m_cRef;
// IUnknown
IUnknown* m_pUnknownInner;
};

, ,
IY: IY - .
IY .
QueryInterface, .
- m_pUnknownInner IUnknown .
HRESULT __stdcall CA::QueryInterface(const IID& iid, void** ppv)
{
if (iid == IID_IUnknown)
{
*ppv = static_cast<IX*>(this);
}
else if (iid = IID_IX)
{
*ppv = static_cast<IX*>(this);
}
else if (iid = IID_IY)
{
return m_pUnknownInner->QueryInterface(iid, ppv);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
return S_OK;
}

QueryInterface QueryInterface .
, !
IUnknown .
- QueryInterface
. , IUnknown.

114
, IUnknown
. , IUnknown.
, ,
. , ,
( , ).

IUnknown
, , ,
.
, . ,
,
. QueryInterface ,
QueryInterface.
, ,
(. 8-4).
. , .
IX IY. IX IY.
IY IZ. , IUnknown.
IX IY, IZ
E_NOINTERFACE. IY,
. IZ IY, . - ,
IUnknown IY . ,
IY IX , IX.
QueryInterface:
-, .

IX
QueryInterface
AddRef

IUnknown

Release
Fx


IY
QueryInterface
AddRef
Release

IUnknown

Fy

. 8-4 IUnknown
IUnknown . IUnknown,
. IUnknown QueryInterface -,
QueryInterface .
-. , ,
IUnknown . . 3,
,
IUnknown. , IUnknown
IUnknown .
IUnknown, . IUnknown IUnknown
(outer unknown), IUnknown (controlling unknown).

115

IUnknown
IUnknown
IUnknown. , ,
IUnknown.
IUnknown
. 7 , CoCreateInstance IClassFactory::CreateInstance
IUnknown, :
HRESULT __stdcall CoCreateInstance(
const CLSID& clsid,
IUnknown* pUnknownOuter,
DWORD dwClsContext,
const IID& iid,
void** ppv
);

//
//

HRESULT __stdcall CreateInstance(


IUnknown* pUnknownOuter,
const IID& iid,
void** ppv
);

IUnknown
pUnknownOuter. IUnknown NULL, .
IUnknown, CreateInstance, ,
. , IUnknown.
IUnknown.
IUnknown
IUnknown.
(nondelegating) IUnknown IUnknown .
(delegating) IUnknown IUnknown IUnknown,
IUnknown. , IUnknown
IUnknown, .
IUnknown, .
: . 8-5, .
8-6.

IUnknown
IY
QueryInterface
AddRef
Release

IUnknown

Fy

. 8-5 ,
IUnknown IUnknown
. 8-6 , IY. IUnknown
IUnknown, . IUnknown
. ,
IUnknown IY, IUnknown,
IUnknown.
IUnknown .
, , IUnknown.

116

IX
QueryInterface
AddRef


IUnknown

Release
Fx


IY
QueryInterface
AddRef
Release

IUnknown

IUnknown

Fy

. 8-6 , IUnknown
IUnknown
IUnknown
IUnknown. ++
. , IUnknown,
. InondelegatingUnknown. , .
, ; vtbl.
InondelegatingUnknown , IUnknown, , Nondelegating.
struct InondelegatingUnknown
{
virtual HRESULT __stdcall NondelegatingQueryInterface(const IID&, void**) = 0;
virtual ULONG __stdcall NondelegatingAddRef() = 0;
virtual ULONG __stdcall NondelegatingRelease() = 0;
};

NondelegatingAddRef NondelegatingRelease InondelegatingUnknown


, AddRef Release IUnknown. NondelegatingQueryInterface
, .
HRESULT __stdcall CB::NondelegatingQueryInterface(const IID& iid, void** ppv)
{
if (iid == IID_IUnknown)
{
*ppv = static_cast<INondelegatingUnknown*>(this);
}
else if (iid = IID_IY)
{
*ppv = static_cast<IY*>(this);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
return S_OK;
}

this INondelegatingUnknown.
. this INondelegatingUnknown, ,
IUnknown. IUnknown ,
IID_IUnknown. IUnknown
. , IUnknown QueryInterface,
Release AddRef .

117
IUnknown
. , IUnknown, IUnknown
. IUnknown
. , IUnknown.
IUnknown
, IUnknown ,
IUnknown. , .
m_pUnknownOuter. ,
IUnknown. , IUnknown.
IUnknown ,
m_pUnknownOuter. IUnknown , (inline):
class CB : public IY, INondelegatingUnknown
{
public:
// IUnknown
virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv)
{
// QueryInterface
return m_pUnknownOuter->QueryInterface(iid, ppv);
}
virtual ULONG __stdcall AddRef()
{
// AddRef
return m_pUnknownOuter->AddRef();
}
virtual ULONG __stdcall Release()
{
// Release
return m_pUnknownOuter->Release();
}
// IUnknown
virtual HRESULT __stdcall
NondelegatingQueryInterface(const IID& iid, void** ppv);
virtual ULONG __stdcall NondelegatingAddRef();
virtual ULONG __stdcall NondelegatingRelease();
// IY
virtual void Fy() { cout << Fy << endl; }
//
CB(IUnknown* pUnknownOuter);
//
~CB();
private:
long m_cRef;
IUnknown* m_pUnknownOuter;
};


, , , ,
. , , :
Init ; CreateInstance
.
Init
, .
,
IUnknown. ,

118
. , CoCreateInstance IUnknown
.
, , IUnknown.
IUnknown .
, QueryInstance
. IUnknown;
. IUnknown
.
this IUnknown, CA
IX, , , .
HRESULT CA::Init()
{
IUnknown* pUnknownOuter = this;
HRESULT hr = CoCreateInstance(CLSID_Component2,
pUnknownOuter,
CLSCTX_INPROC_SERVER,
IID_IUnknown,
(void**)&m_pUnknownOuter);
if (FAILED(hr))
{
return E_FAIL;
}
return S_OK;
}

IClassFactory::CreateInstance CA::Init.
IClassFactory .
, .
IClassFactory::CreateInstance

IClassFactory::CreateInstance

,
InondelegatingUnknown IUnknown. ,
CreateInstance , pUnknownOuter NULL (..
). CreateInstance ,
iid IID_IUnknown. ,
IUnknown, IUnknown (
QueryInterface IUnknown).
HRESULT __stdcall Cfactory::CreateInstance(IUnknown* pUnknownOuter,
const IID& iid,
void** ppv)
{
// iid IID_IUnknown
if ((pUnknownOuter != NULL) && (iid != IID_IUnknown))
{
return CLASS_E_NOAGGREGATION;
}
//
CB* pB = new CB(pUnknownOuter);
if (pB == NULL)
{
return E_OUTOFMEMORY;
}
//
HRESULT hr = pB->NondelegatingQueryInterface(iid, ppv);
PB->NondelegatingRelease();
return hr;
}


CreateInstance QueryInterface, NondelegatingQueryInterface.
, QueryInterface IUnknown.
QueryInterface, NondelegatingQueryInterface.

119

CreateInstance IUnknown
. m_pUnknownOuter, IUnknown
, IUnknown.
(pUnknownOuter NULL), m_pUnknownOuter
IUnknown. :
CB::CB(IUnknown* pUnknownOuter) : m_cRef(1)
{
::InterlockedIncrement)&g_cComponents;
if (pUnknownOuter == NULL)
{
// : IUnknown
m_pUnknownOuter = reinterpret_cast<IUnknown*>(
static_cast<INondelegatingUnknown*>(this)
);
}
else
{
// : IUnknown
m_pUnknownOuter = pUnknownOuter;
}
}


CA::Init , IUnknown, IY.
IY. ,
IY . , ,
IUnknown. Cfactory::CreateInstance
CLASS_E_NOAGGREGATION, -, IID_IUnknown.
, IY ()
.
. QueryInterface,
m_pUnknownInner IID_IY, , ,
AddRef. , AddRef
IUnknown. , .
.
IUnknown - ,
. , ,
. IY
, .
, ! ,
, .
IY, ,
, .
Release IY IY ,
. ( ,
Release. .) IY
. , , Release,
, CoCreateInstance. CA::Init, IY, :
HRESULT __stdcall CA::Init()
{
// IUnknown
IUnknown* pUnknownOuter = this;
//
HRESULT hr = CoCreateInstance(CLSID_Component2,
PUnknownOuter,
// IUnknown
CLSCTX_INPROC_SERVER,
IID_IUnknown,
// IUnknown
(void**)&m_pUnknownInner);
if (FAILED(hr))

120
{
//
return E_FAIL;
}
//
//
hr
if
{


IY
= m_pUnknownInner->QueryInterface(IID_IY, (void**)&m_pIY);
(FAILED(hr))
// IY
m_pUnknownInner->Release();
return E_FAIL;

}
// ,
//
pUnknownOuter->Release();
return S_OK;
}

QueryInterface m_pIY, QueryInterface


.
else if (iid == IID_IY)
{
return m_pUnknownOuter->QueryInterface(iid, ppv);
}

,
else if (iid == IID_IY)
{
*ppv = m_pIY;
}

, , ,
. ,
. m_pIY->Release, .
Init , IY.
, Release IY.
, Release
, .
,
. -, , . -,
AddRef , Release
Release . , , IY,
. :
// 1.
//

m_cRef = 1;
// 2. AddRef IUnknown
IUnknown* pUnknownOuter = this;
pUnknownOuter->AddRef();
// 3.
m_pIY->Release();

. , ,
1. . Release IY.
. 2 1.
1, .
, , Release
IUnknown. ,
,
, Release .
.

121
.
, .
. 9 , , .
, , , . ,
, , , .
aggregation, aggravation*.


, . 1
, . IX.
IY, 2. ,
1 IY, 1 IY,
2. 8-3 , 8-4
. ; ,
.
AGGRGATE\CMPNT1
//
// Cmpnt1.cpp - 1
//
//

//
#include <iostream.h>
#include <objbase.h>
#include "Iface.h"
#include "Registry.h"
// Trace
void trace(const char* msg) { cout << " 1:\t" << msg << endl; }
///////////////////////////////////////////////////////////
//
//
//
//
static HMODULE g_hModule = NULL;
static long g_cComponents = 0;
static long g_cServerLocks = 0;

// DLL
//
//

//
const char g_szFriendlyName[] = " COM, 8 2, 1";
// ProgID
const char g_szVerIndProgID[] = "InsideCOM.Chap08.Ex2.Cmpnt1";
// ProgID
const char g_szProgID[] = "InsideCOM.Chap08.Ex2.Cmpnt1.1";
///////////////////////////////////////////////////////////
//
// A
//
class CA : public IX //, public IY
{
public:
// IUnknown
virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);
virtual ULONG
__stdcall AddRef();
virtual ULONG
__stdcall Release();
// IX

Aggravation (.) 1. , ; 2. , . . .

122
virtual void __stdcall Fx() { cout << "Fx" << endl; }
/* 1 IY,
// IY
virtual void __stdcall Fy() { m_pIY->Fy(); }
*/
//
CA();
//
~CA();
// ,
//
HRESULT __stdcall Init();
private:
//
long m_cRef;
// IY
// ( IY.
// QueryInterface)
IY* m_pIY;
// IUnknown
IUnknown* m_pUnknownInner;
};

//
//
//
CA::CA() : m_cRef(1), m_pUnknownInner(NULL)
{
::InterlockedIncrement(&g_cComponents);
}
//
//
//
CA::~CA()
{
::InterlockedDecrement(&g_cComponents);
trace("");
//
// AddRef/Release
m_cRef = 1;
// pUnknownOuter->Release Init
IUnknown* pUnknownOuter = this;
pUnknownOuter->AddRef();
// ;
//
m_pIY->Release();
//
if (m_pUnknownInner != NULL)
{
m_pUnknownInner->Release();
}
}
//
HRESULT __stdcall CA::Init()
{
// IUnknown

123
// , IUnknown // , this
IUnknown* pUnknownOuter = this;
trace(" ");
HRESULT hr = ::CoCreateInstance(CLSID_Component2,
pUnknownOuter,
// IUnknown
CLSCTX_INPROC_SERVER,
IID_IUnknown,
// - IUnknown
(void**)&m_pUnknownInner);
if (FAILED(hr))
{
trace(" ");
return E_FAIL;
}
//
trace(" IY ");
hr = m_pUnknownInner->QueryInterface(IID_IY, (void**)&m_pIY);
if (FAILED(hr))
{
trace(" IY");
m_pUnknownInner->Release();
return E_FAIL;
}
// ,
// . Release ,
// CoCreateInstance.
pUnknownOuter->Release();
return S_OK;
}
//
// IUnknown
//
HRESULT __stdcall CA::QueryInterface(const IID& iid, void** ppv)
{
if (iid == IID_IUnknown)
{
*ppv = static_cast<IUnknown*>(this);
}
else if (iid == IID_IX)
{
*ppv = static_cast<IX*>(this);
}
else if (iid == IID_IY)
{
trace(" IY ");
#if 1
// ...
return m_pUnknownInner->QueryInterface(iid,ppv);
#else
//
*ppv = m_pIY;
// , AddRef
#endif
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
return S_OK;
}
ULONG __stdcall CA::AddRef()
{
return ::InterlockedIncrement(&m_cRef);

124
}
ULONG __stdcall CA::Release()
{
if (::InterlockedDecrement(&m_cRef) == 0)
{
delete this;
return 0;
}
return m_cRef;
}
///////////////////////////////////////////////////////////
//
//
//
class CFactory : public IClassFactory
{
public:
// IUnknown
virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);
virtual ULONG
__stdcall AddRef();
virtual ULONG
__stdcall Release();
// IClassFactory
virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter,
const IID& iid,
void** ppv);
virtual HRESULT __stdcall LockServer(BOOL bLock);
//
CFactory() : m_cRef(1) {}
//
~CFactory() {}
private:
long m_cRef;
};
//
// IUnknown
//
HRESULT __stdcall CFactory::QueryInterface(REFIID iid, void** ppv)
{
IUnknown* pI;
if ((iid == IID_IUnknown) || (iid == IID_IClassFactory))
{
pI = static_cast<IClassFactory*>(this);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
pI->AddRef();
*ppv = pI;
return S_OK;
}
ULONG __stdcall CFactory::AddRef()
{
return ::InterlockedIncrement(&m_cRef);
}
ULONG __stdcall CFactory::Release()
{
if (::InterlockedDecrement(&m_cRef) == 0)
{
delete this;

125
return 0;
}
return m_cRef;
}
//
// IClassFactory
//
HRESULT __stdcall CFactory::CreateInstance(IUnknown* pUnknownOuter,
const IID& iid,
void** ppv)
{
//
if (pUnknownOuter != NULL)
{
return CLASS_E_NOAGGREGATION;
}
//
CA* pA = new CA;
if (pA == NULL)
{
return E_OUTOFMEMORY;
}
//
HRESULT hr = pA->Init();
if (FAILED(hr))
{
// . .
pA->Release();
return hr;
}
//
hr = pA->QueryInterface(iid, ppv);
pA->Release();
return hr;
}
// LockServer
HRESULT __stdcall CFactory::LockServer(BOOL bLock)
{
if (bLock)
{
::InterlockedIncrement(&g_cServerLocks);
}
else
{
::InterlockedDecrement(&g_cServerLocks);
}
return S_OK;
}
///////////////////////////////////////////////////////////
//
//
//
STDAPI DllCanUnloadNow()
{
if ((g_cComponents == 0) && (g_cServerLocks == 0))
{
return S_OK;
}
else
{
return S_FALSE;
}
}

126
//
//
//
STDAPI DllGetClassObject(const CLSID& clsid,
const IID& iid,
void** ppv)
{
// ?
if (clsid != CLSID_Component1)
{
return CLASS_E_CLASSNOTAVAILABLE;
}
//
CFactory* pFactory = new CFactory;
if (pFactory == NULL)
{
return E_OUTOFMEMORY;
}

// Addref

//
HRESULT hr = pFactory->QueryInterface(iid, ppv);
pFactory->Release();
return hr;
}
//
//
//
STDAPI DllRegisterServer()
{
return RegisterServer(g_hModule,
CLSID_Component1,
g_szFriendlyName,
g_szVerIndProgID,
g_szProgID);
}
STDAPI DllUnregisterServer()
{
return UnregisterServer(CLSID_Component1,
g_szVerIndProgID,
g_szProgID);
}
///////////////////////////////////////////////////////////
//
// DLL
//
BOOL APIENTRY DllMain(HANDLE hModule,
DWORD dwReason,
void* lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
g_hModule = hModule;
}
return TRUE;
}

8-3 ()
AGGRGATE\CMPNT2
//
// Cmpnt2.cpp - 2
//
,
//
#include <iostream.h>

127
#include <objbase.h>
#include "Iface.h"
#include "Registry.h"
void trace(const char* msg) { cout << " 2:\t" << msg << endl; }
///////////////////////////////////////////////////////////
//
//
//
//
static HMODULE g_hModule = NULL;
static long g_cComponents = 0;
static long g_cServerLocks = 0;

// DLL
//
//

//
const char g_szFriendlyName[]
= " COM, 8 2, 2";
// ProgID
const char g_szVerIndProgID[] = "InsideCOM.Chap08.Ex2.Cmpnt2";
// ProgID
const char g_szProgID[] = "InsideCOM.Chap08.Ex2.Cmpnt2.1";
///////////////////////////////////////////////////////////
//
// IUnknown
//
struct INondelegatingUnknown
{
virtual HRESULT __stdcall
NondelegatingQueryInterface(const IID&, void**) = 0;
virtual ULONG __stdcall NondelegatingAddRef() = 0;
virtual ULONG __stdcall NondelegatingRelease() = 0;
};
///////////////////////////////////////////////////////////
//
// B
//
class CB : public IY, public INondelegatingUnknown
{
public:
// IUnknown
virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv)
{
trace(" QueryInterface");
return m_pUnknownOuter->QueryInterface(iid, ppv);
}
virtual ULONG __stdcall AddRef()
{
trace(" AddRef");
return m_pUnknownOuter->AddRef();
}
virtual ULONG __stdcall Release()
{
trace(" Release");
return m_pUnknownOuter->Release();
}
// IUnknown
virtual HRESULT __stdcall
NondelegatingQueryInterface(const IID& iid, void** ppv);
virtual ULONG
__stdcall NondelegatingAddRef();
virtual ULONG
__stdcall NondelegatingRelease();

128
// IY
virtual void __stdcall Fy() { cout << "Fy" << endl; }
//
CB(IUnknown* m_pUnknownOuter);
//
~CB();
private:
long m_cRef;
IUnknown* m_pUnknownOuter;
};
//
// IUnknown
//
HRESULT __stdcall CB::NondelegatingQueryInterface(const IID& iid, void** ppv)
{
if (iid == IID_IUnknown)
{
// !!! !!!
*ppv = static_cast<INondelegatingUnknown*>(this);
}
else if (iid == IID_IY)
{
*ppv = static_cast<IY*>(this);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
return S_OK;
}
ULONG __stdcall CB::NondelegatingAddRef()
{
return ::InterlockedIncrement(&m_cRef);
}
ULONG __stdcall CB::NondelegatingRelease()
{
if (::InterlockedDecrement(&m_cRef) == 0)
{
delete this;
return 0;
}
return m_cRef;
}
//
//
//
CB::CB(IUnknown* pUnknownOuter) : m_cRef(1)
{
::InterlockedIncrement(&g_cComponents);
if (pUnknownOuter == NULL)
{
trace(" ; IUnknown");
m_pUnknownOuter = reinterpret_cast<IUnknown*>
(static_cast<INondelegatingUnknown*>
(this));
}
else
{

129
trace("; IUnknown");
m_pUnknownOuter = pUnknownOuter;
}
}
//
//
//
CB::~CB()
{
::InterlockedDecrement(&g_cComponents);
trace("");
}
///////////////////////////////////////////////////////////
//
//
//
class CFactory : public IClassFactory
{
public:
// IUnknown
virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);
virtual ULONG
__stdcall AddRef();
virtual ULONG
__stdcall Release();
// IClassFactory
virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter,
const IID& iid,
void** ppv);
virtual HRESULT __stdcall LockServer(BOOL bLock);
//
CFactory() : m_cRef(1) {}
//
~CFactory() {}
private:
long m_cRef;
};
//
// IUnknown
//
HRESULT __stdcall CFactory::QueryInterface(const IID& iid, void** ppv)
{
if ((iid == IID_IUnknown) || (iid == IID_IClassFactory))
{
*ppv = static_cast<IClassFactory*>(this);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
return S_OK;
}
ULONG __stdcall CFactory::AddRef()
{
return ::InterlockedIncrement(&m_cRef);
}
ULONG __stdcall CFactory::Release()
{
if (::InterlockedDecrement(&m_cRef) == 0)
{
delete this;

130
return 0;
}
return m_cRef;
}
//
// IClassFactory
//
HRESULT __stdcall CFactory::CreateInstance(IUnknown* pUnknownOuter,
const IID& iid,
void** ppv)
{
// iid IID_IUnknown
if ((pUnknownOuter != NULL) && (iid != IID_IUnknown))
{
return CLASS_E_NOAGGREGATION;
}
//
CB* pB = new CB(pUnknownOuter);
if (pB == NULL)
{
return E_OUTOFMEMORY;
}
//
HRESULT hr = pB->NondelegatingQueryInterface(iid, ppv);
pB->NondelegatingRelease();
return hr;
}
// LockServer
HRESULT __stdcall CFactory::LockServer(BOOL bLock)
{
if (bLock)
{
::InterlockedIncrement(&g_cServerLocks);
}
else
{
::InterlockedDecrement(&g_cServerLocks);
}
return S_OK;
}
///////////////////////////////////////////////////////////
//
//
//
STDAPI DllCanUnloadNow()
{
if ((g_cComponents == 0) && (g_cServerLocks == 0))
{
return S_OK;
}
else
{
return S_FALSE;
}
}
//
//
//
STDAPI DllGetClassObject(const CLSID& clsid, const IID& iid, void** ppv)
{
// ?
if (clsid != CLSID_Component2)
{

131
return CLASS_E_CLASSNOTAVAILABLE;
}
//
CFactory* pFactory = new CFactory;
if (pFactory == NULL)
{
return E_OUTOFMEMORY;
}

// AddRef

//
HRESULT hr = pFactory->QueryInterface(iid, ppv);
pFactory->Release();
return hr;
}
//
//
//
STDAPI DllRegisterServer()
{
return RegisterServer(g_hModule,
CLSID_Component2,
g_szFriendlyName,
g_szVerIndProgID,
g_szProgID);
}
STDAPI DllUnregisterServer()
{
return UnregisterServer(CLSID_Component2,
g_szVerIndProgID,
g_szProgID);
}
///////////////////////////////////////////////////////////
//
// DLL
//
BOOL APIENTRY DllMain(HANDLE hModule,
DWORD dwReason,
void* lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
g_hModule = hModule;
}
return TRUE;
}

8-4 ()



. , , IY.
IZ, IZ,
E_NOINTERFACE.
, ?
, :
else is ((iid == IID_IY) || (iid == IID_IZ))
{
return m_pUnknownInner->QueryInterface(iid, ppv);
}

, .
, , , ,
, , ?

132
.
:
...
else if (iid == IID_IX)
{
*ppv = static_cast<IX*>(this);
}
else
//
{
return m_pUnknownInner->QueryInterface(iid, ppv);
}
...

(blind aggregation),
.
, .
. ,
, , .
, ISlowFile,
IFastFile. ,
IFastFile , ISlowFile. ,
IFastFile .
, .
, .
,
. -,
, . -,

.

, ,
. ,
, . ,
, .

(metainterfaces), . ,
, .
, .
.
, .
,
. ISetColors, ,
. IToolInfo,
,
(. 8-7).
ISetColors , .
, , , , IColors,
. , IToolInfo . ,
.
.
,
.
,
. ,
, , .
.
,
.

133

IToolInfo
ISetColors

IMorph
IColors

. 8-7 IToolInfo ,
. ISetColors
.
ISetColors IColors .


. , ,
, ,
. ,
, . ,
, .


,
. .
, ,
.
. , ,
, .
, ,

- . ,
.
, .
,
. ++, , ,
, . ++,
, ,
.
, .


. ,
, .
, (. 8-8).
. ,
, ,
.
, .

134

IX


IInternalState


IInternalState
IY
IZ

IInternalState


. 8-8 ,
,

, , .
.
, -
. ,
, (
) (. 8-9). ,
. .

IX

IX

IX

IY

IY

IY

IZ

IZ

IZ

IX, IY, IZ

. 8-9 .
.
. ,
, .


-
++, .
(callback).
, ,
. , (customization
interface). , , , . ,
, .
, (. 8-10).

IX

ICustomize

IX

ICustomize,

IX

. 8-10 ,

135

(outgoing) , ICustomize, ,
. . 13. ,
. ICustomize
.

. -
. ,
.
. , , ,
, . , ++
, . 8-11. ++
, ,
. ,
, , .
,
, .

IX

ICustomize

ICustomize


,

IX


ICustomize

ICustomize


,


IX


,

ICustomize

. 8-11

, ,
. ,
. .
, .
, .
, , .
, , .
.
, .
IUnknown. IUnknown.
IUnknown, , IUnknown,
, .

. .
,
. ,
, .
.
: ++.
IUnknown IClassFactory, .
. , ,
. , .

9

, , ,
, .
, , .
, . ( ,
, , . )
,
. , , , , ,
, .
++
; , .


, ,
++. -, . AddRef
, . ,
, .
AddRef Release . ,
. (
), , , .

Microsoft Visual C++ 5.0 ++,
.
Visual ++ 5.0.
Release , , .
++ . Release
.
AddRef Release . QueryInterface,
, , , .
. , ,
. .
QueryInterface .
, QueryInterface, . ,
, IY - IZ:
IZ* pIZ;
PIX->QueryInterface(IID_IY, (void**)&pIZ);

void , .
.
smart-, -
(wrapper). , smart-.

Smart-
smart-
. Smart- , ++,

138
. -smart-,
.
++.
smart-?
Smart- (smart pointer) , operator-> ( ).
smart- . smart- operator->,
smart- ,
. Smart- smart-, .
. CFooPointer , smart-.
operator->.
class CFoo
{
public:
virtual void Bar();
};
class CFooPointer
{
public:
CFooPointer (Cfoo*p) { m_p = p; }
CFoo* operator->() { return m_p; }
private:
CFoo* m_p;
};
...
void Funky(CFoo* pFoo)
{
// smart-
CFooPointer spFoo(pFoo);
// pFoo->Bar();
spFoo->Bar();
}

Funky CFooPointer spFoo


pFoo. spFoo Bar. spFoo
m_p, pFoo. spFoo CFoo.
, CFooPointer CFoo. CFoo operator->
*. CFooPointer , m_p (. .
9-1)**.
(smart) CFooPointer . . , ,
. , CFooPointer .
pFoo spFoo. , operator= (
) . , CFooPointer ,
CFoo, CFooPointer . operator*
( ) operator& ( ),
m_p, CFooPointer.

smart- , ,
. ActiveX Template Library (ATL)
CComPtr CComQIPtr. MFC CIP . (
AFXCOM_.H.) CIP smart- .
. , , .
ATL MFC, .

, CFoo*. . .

**

operator-> , - ..
.

139


operator->

-

smart-


""

smart-

m_pIX

IX

IY
IZ

. 9-1 Smart-
, .
IPtr PTR.H,
9-1. . . ,
.
IPtr PTR.H
//
// IPtr Smart-
//
: IPtr<IX, &IID_IX> spIX;
//
IUnknown; IPtr<IUnknown, &IID_IUnknown>
//
. IUnknownPtr.
//
template <class T, const IID* piid> class IPtr
{
public:
//
IPtr()
{
m_pI = NULL;
}
IPtr(T* lp)
{
m_pI = lp;
if (m_pI != NULL)
{
m_pI->AddRef();
}
}
IPtr(IUnknown* pI)
{
m_pI = NULL;
if (pI != NULL)
{
pI->QueryInterface(*piid, (void **)&m_pI);
}
}
//
~IPtr()
{
Release();
}
// NULL
void Release()

140
{
if (m_pI != NULL)
{
T* pOld = m_pI;
m_pI = NULL;
pOld->Release();
}
}
//
operator T*() { return m_pI; }
//
T& operator*() { assert(m_pI != NULL); return *m_pI; }
T** operator&() { assert(m_pI == NULL); return &m_pI; }
T* operator->() { assert(m_pI != NULL); return m_pI; }
//
T* operator=(T* pI)
{
if (m_pI != pI)
{
IUnknown* pOld = m_pI;
m_pI = pI;
if (m_pI != NULL)
{
m_pI->AddRef();
}
if (pOld != NULL)
{
pOld->Release();
}
}
return m_pI;
}
//
T* operator=(IUnknown* pI)
{
IUnknown* pOld = m_pI;
m_pI == NULL ;

//
//

//

//

//
if (pI != NULL)
{
HRESULT hr = pI->QueryInterface(*piid, (void**)&m_pI);
assert(SUCCEEDED(hr) && (m_pI != NULL));
}
if (pOld != NULL)
{
pOld->Release();
}
return m_pI;

//

}
//
BOOL operator!() { return (m_pI == NULL) ? TRUE : FALSE; }
// , BOOL
operator BOOL() const
{
return (m_pI != NULL) ? TRUE : FALSE;
}
// GUID
const IID& iid() { return *piid; }
private:
//

141
T* m_pI;
};

9-1. smart- IPtr.



IPtr , . -, ,
IID. ( ,
.) CoCreateInstance
. ,
IPtr . IPtr operator&
:
void main()
{
IPtr<IX, &IID_IX> spIX;
HRESULT hr = ::CoCreateInstance(CLSID_Component1,
NULL,
CLSCTX_ALL,
spIX.iid(),
(void**)&spIX);
if (SUCCEEDED(hr))
{
spIX->Fx();
}
}

CoCreateInstance , ,
IPtr :
HRESULT CreateInstance(const CLSID& clsid, IUnkown* pI, DWORD clsctx)
{
Release();
return CoCreateInstance(clsid, pI, clsctx, *piid, (void**)&m_pI);
}

:
IPtr<IX, &IID_IX> spIX;
HRESULT hr = spPX.CreateInstance(CLSID_Component1, NULL, CLSCTX_INPROC_SERVER);

, -smart- sp, smart , .



smart- , Release.
smart-,
Release. , ,
smart- ++.
, smart-, Release.
Smart- , , .
, , smart- - NULL.
smart- .
smart- , .
, IPtr, Release, ,
operator->:
spIX.Release();

IPtr NULL:
spIX = NULL;

, , , IPtr .

IPtr operator=, smart-:

142
T* operator=(T* pI)
{
if (m_pI != pI)
{
IUnknown* pOld = m_pI;
m_pI = pI;
if (m_pI != NULL)
{
m_pI->AddRef();
}
if (pOld != NULL)
{
pOld->Release();
}
}
return m_pI;
}

operator=. -, AddRef Release,


. -, smart-
.
.
pIX1 m_p spIX.
AddRef. spIX pIX2.
operator= ,
pIX1, pIX2 AddRef pIX2.
void Fuzzy(IX* pIX1, IX* pIX2)
{
IPtr<IX, &IID_IX> spIX;
spIX=pIX1;
spIX->Fx();
spIX = pIX2;
spIX->Fx();
}

, IPtr IPtr
. :
typedef IPtr<IX, &IID_IX> SPIX;
SPIX g_spIX;
void Wuzzy(SPIZ spIX)
{
g_spIX = spIX;
}

, .
typedef .
IUnknown
, QueryInterface.
.
T* operator=(IUnknown* pIUnknown);

, smart-,
QueryInterface. ,
IY smart- IX. , ,
. smart- ,
QueryInterface .
void WasABear(IY* pIY)
{
IPtr<IX, &IID_IX> spIX;
spIX = pIY;
if (spIX)
{
spIX->Fx();
}
}

143
, QueryInterface.
, , . ,
QueryInterface . ++
. QueryInterface ,
.
, . Microsoft Visual Basic
, QueryInterface. Smart- ATL MFC
, QueryInterface.
interface_cast

. , Visual Basic QueryInterface, ,
++ . , ++ ,
Visual Basic .
QueryInterface , interface_cast.
interface_cast -, dynamic_cast. :
template <class I, const GUID* pGUID>
I* interface_cast(IUnknown* pIUnknown)
{
I* pI = NULL;
HRESULT hr = pIUnknown->QueryInterface(*pGUID, (void**)&pI);
assert(SUCCEEDED(hr));
return pI;
}

interface_cast :
IY* pIX = interface_cast<IY, &&IID_IY>(this);

interface_cast , smart-.
, ,
(explicit instantiation) -. , Visual C++ 5.0
.
IUnknownPtr
IPtr PTR.H IUnknownPtr IPtr,
IUnknown. IUnknownPtr ,
QueryInterface. IUnknownPtr , IPtr IUnknown
. IPtr IUnknown
. IPtr smart- IUnknown:
IPtr<IUnknown, &IID_IUnknown> spIUnknown;

//

IUnknownPtr:
IUnknownPtr spIUnknown;

smart-
, , . 1
, . 2 smart-. 9-2
2. , QueryInterface , . ,
typedef . ,
, Think.
CLIENT2.CPP
//
// Client2.cpp smart-
//
#include <objbase.h>
#include "Iface.h"
#include "Util.h"
#include "Ptr.h"

//
// smart-

144
static inline void trace(const char* msg)
{ Util::Trace(" 2", msg, S_OK); }
static inline void trace(const char* msg, HRESULT hr)
{ Util::Trace(" 2", msg, hr); }
void Think()
{
trace(" 1");
IPtr<IX, &IID_IX> spIX;
HRESULT hr = CoCreateInstance(CLSID_Component1,
NULL,
CLSCTX_INPROC_SERVER,
spIX.iid(),
(void**)&spIX);
if (SUCCEEDED(hr))
{
trace(" ");
spIX->Fx();
trace(" IY");
IPtr<IY, &IID_IY> spIY;
spIY = spIX;
//
if (spIY)
{
spIY->Fy();
trace(" IX IY");
IPtr<IX, &IID_IX> spIX2(spIY);
//
if (!spIX2)
{
trace(" IX IY");
}
else
{
spIX2->Fx();
}
}
trace(" IZ");
IPtr<IZ, &IID_IZ> spIZ;
spIZ = spIX;
if (spIZ)
{
spIZ->Fz();
trace(" IX IZ");
IPtr<IX, &IID_IX> spIX2(spIZ);
if (!spIX2)
{
trace(" IX IZ");
}
else
{
spIX2->Fx();
}
}
}
else
{
trace(" ", hr);
}
}
int main()
{
// COM
CoInitialize(NULL);
// smart-

145
Think();
// COM
CoUninitialize();
return 0;
}

9-2 2 smart- IPtr


, QueryInterface.
BOOL,
TRUE, IPtr::m_p NULL. operator!.
smart-
. Release smart-
. smart- , ,
.
smart-. ,
( IUnknown).
smart- . Smart-
, ,
. .
.

- C++
Smart- , .
- ++. - (wrapper class)
, .
-, . , , - MFC
Win32 (. 9-2).
- , ++,
, ;
++ - . Visual C++ ,
- ActiveX
.

m_pIX

IX

m_pIY

IY

m_pIZ

IZ

. 9-2 -

-
smart-, - ,
,
. - smart- ,
.
, , -
, smart- .

146

- .
, .
,
. ,
.
, , .
.
. ,
. ++
. OLE MFC, ,
-.
smart-, - smart- -
.


, .
. .
. CUnknown , IUnknown.
CUnknown, AddRef Release,
QueryInterface .
IClassFactory, ,
CUnknown. , CFactory ,
CLSID . CFactory CFactory ,
. CUnknown
CFactory , . ,
CUnknown CFactory. ,
.

CUnknown
. 8 , IUnknown:
. , IUnknown IUnknown
. IUnknown.
, , CUnknown
InondelegatingUnknown, IUnknown. CUnknown 9-3.
CUNKNOWN.H
#ifndef __CUnknown_h__
#define __CUnknown_h__
#include <objbase.h>
///////////////////////////////////////////////////////////
//
// IUnknown
//
- IUnknown
//
interface INondelegatingUnknown
{
virtual HRESULT __stdcall
NondelegatingQueryInterface(const IID& iid, void** ppv) = 0;
virtual ULONG
__stdcall NondelegatingAddRef() = 0;
virtual ULONG
__stdcall NondelegatingRelease() = 0;
};

///////////////////////////////////////////////////////////
//
// CUnknown
//
- IUnknown
//

147
class CUnknown : public INondelegatingUnknown
{
public:
// IUnknown
virtual HRESULT __stdcall NondelegatingQueryInterface(const IID&, void**);
virtual ULONG
__stdcall NondelegatingAddRef();
virtual ULONG
__stdcall NondelegatingRelease();
//
CUnknown(IUnknown* pUnknownOuter);
//
virtual ~CUnknown();
// ( )
virtual HRESULT Init() { return S_OK; }
//
virtual void FinalRelease();
//
static long ActiveComponents() { return s_cActiveComponents; }
//
HRESULT FinishQI(IUnknown* pI, void** ppv);
protected:
//
IUnknown* GetOuterUnknown() const
{ return m_pUnknownOuter ;}
private:
//
long m_cRef;
// IUnknown
IUnknown* m_pUnknownOuter;
//
static long s_cActiveComponents;
};

///////////////////////////////////////////////////////////
//
// IUnknown
//
- IUnknown
//
IUnknown,
//
#define DECLARE_IUNKNOWN
virtual HRESULT __stdcall
QueryInterface(const IID& iid, void** ppv)
{
return GetOuterUnknown()->QueryInterface(iid,ppv);
};
virtual ULONG __stdcall AddRef()
{
return GetOuterUnknown()->AddRef();
};
virtual ULONG __stdcall Release()
{
return GetOuterUnknown()->Release();
};

\
\
\
\
\
\
\
\
\
\
\
\
\

///////////////////////////////////////////////////////////
#endif

9-3 CUnknown IUnknown. DECLARE_IUNKNOWN


IUnknown

148
INondelegatingUnknown CUnknown ,
. 8. , CUnknown ,
. ,
, NondelegatingQueryInterface.
CUnknown CUNKNOWN.CPP .
. .
DECLARE_IUNKNOWN
IUnknown , .
, CUnknown. 9-3, ,
DECLARE_IUNKNOWN, IUnknown. , , ,
, , . ActiveX Template Library
; , .
INondelegatingUnknown
; ,
CUnknown INondelegatingUnknown, IUnknown:
, . ,
IUnknown. CA IUnknown
. IUnknown CUnknown .
CA CUnknown, IUnknown, -
IUnknown.
, CA IUnknown CUnknown, IX. IX
- IUnknown, - , CA .
CA CUnknown.
CUnknown INondelegatingUnknown. . 9-3.
NondelegatingUnknown

IUnknown

IX

CUnknown
NondelegatingQueryInterface
NondelegatingAddRef
NondelegatingRelease

IUnknown


CUnknown,

CA
QueryInterface
AddRef

DECLARE_IUNKNOWN

Release

. 9-3 CUnknown IUnknown,


IX. CUnknown
INondelegatingUnknown. IUnknown
GetOuterUnknown
9-3 DECLARE_IUNKNOWN CUnknown::
GetOuterUnknown, IUnknown. CUnknown
, GetOuterUnknown INondelegatingUnknown .
, IUnknown .
, IUnknown, GetOuterUnknown.
: GetOuterUnknown AddRef,
.

149
CUnknown
IUnknown, CUnknown
GetOuterUnknown. ,
CUnknown, IUnknown CUnknown.
Init FinalRelease
CUnknown ,
. ,
Init. CUnknown::Init CFactory::CreateInstance
. CUnknown::FinalRelease CUnknown::NondelegatingRelease
.
. CUnknown::FinalRelease Release,
.
, CUnknown.
CFactory, .

CFactory
, .
.
++ CFactory. CFactory IClassFactory,
, DLL, DllGetClassObject.
, CFactory DLL.
IClassFactory. ( .
7.)
CFactory , :
!" , :
HRESULT CreateFunction(IUnknown* pUnknownOuter, CUnknown** ppNewComponent)

IClassFactory::CreateInstance
.
!" CUnknown.
IClassFactory::CreateInstance CFactory
CUnknown::Init.
, , .
!" CfactoryData
g_FactoryDataArray.
, .
CFactory. .

CFactory .
:
HRESULT CreateFunction(IUnknown* pUnknownOuter, CUnknown** ppNewComponent)


ppNewComponent. pUnknownOuter
NULL, .
, .
(name space), . ,
CreateInstance .
CFactory
CFactory , .
g_FactoryDataArray . g_FactoryDataArray
CfactoryData. CfactoryData :

150
typedef HRESULT (*FPCREATEINSTANCE)(IUnknown*, CUnknown**);
class CFactoryData
{
public:
//
const CLSID* m_pCLSID;
// ,
FPCREATEINSTANCE CreateInstance;
//
const char* m_RegistryName;
// ProgID
const char* m_szProgID;
// ProgID
const char* m_szVerIndProgID;
//
BOOL IsClassID(const CLSID& clsid) const
{ return (*m_pCLSID == clsid); }
};

CFactoryData : , ,
Windows, ProgID ProgID.
. 9-4,
SERVER.CPP, CFactoryData .
SERVER.CPP
#include
#include
#include
#include
#include

"CFactory.h"
"Iface.h"
"Cmpnt1.h"
"Cmpnt2.h"
"Cmpnt3.h"

///////////////////////////////////////////////////////////
//
// Server.cpp
//
// .
// FactoryDataArray ,
// .
//
//
//
//
//
//
//

CUnknown
:
HRESULT CreateInstance(IUnknown* pUnknownOuter,
CUnknown** ppNewComponent);
.

//
// , CFactory
// . CLSID,
//
// .
//
CFactoryData g_FactoryDataArray[] =
{
{&CLSID_Component1, CA::CreateInstance,
"Inside COM, Chapter 9 Example, Component 1", //
"InsideCOM.Chap09.Cmpnt1.1",
// ProgID
"InsideCOM.Chap09.Cmpnt1"},
//
//
ProgID
{&CLSID_Component2, CB::CreateInstance,
"Inside COM, Chapter 9 Example, Component 2",
"InsideCOM.Chap09.Cmpnt2.1",
"InsideCOM.Chap09.Cmpnt2"},

151
{&CLSID_Component3, CC::CreateInstance,
"Inside COM, Chapter 9 Example, Component 3",
"InsideCOM.Chap09.Cmpnt3.1",
"InsideCOM.Chap09.Cmpnt3"}
};
int g_cFactoryDataEntries = sizeof(g_FactoryDataArray) / sizeof(CFactoryData);

9-4 , , g_FactoryDataArray
CFactoryData
9-4 g_FactoryDataArray ,
DLL.
CFactory g_FactoryDataArray, , .
, CFactory . CFactory
. , CFactory CFactoryData
. . 9-4 ,
CFactory.
CFACTORY.CPP

DllGetClassObject

CFactory

IClassFactory

CreateInstance

DllRegisterServer
DllUnregisterServer

IX

DllCanUnloadNow

SERVER.CPP
g_FactoryDataArray[]

2
CreateInstance

CFactoryData
CFactoryData

IX

. 9-4 CFactoryData
CFACTORY.H DLL CFactory.
DllGetClassObject CFactory::GetClassObject,
g_FactoryDataArray CfactoryData, ,
. g_FactoryDataArray SERVER.CPP ,
DLL. CFactory::GetClassObject
CfactoryData, .
CFactory IClassFactory::CreateInstance,
, CfactoryData.
CFactory::GetClassObject CFactory::CreateInstance 9-5 9-6.
GetClassObject CFACTORY.CPP
///////////////////////////////////////////////////////////
//
// GetClassObject
//
- CLSID
//
HRESULT CFactory::GetClassObject(const CLSID& clsid, const IID& iid, void** ppv)
{
if ((iid != IID_IUnknown) && (iid != IID_IClassFactory))
{
return E_NOINTERFACE;
}
//
for (int i = 0; i < g_cFactoryDataEntries; i++)
{
const CFactoryData* pData = &g_FactoryDataArray[i];

152
if (pData->IsClassID(clsid))
{
// ,
// .
// .
// , ,
// CFactoryData
*ppv = (IUnknown*) new CFactory(pData);
if (*ppv == NULL)
{
return E_OUTOFMEMORY;
}
return NOERROR;
}
}
return CLASS_E_CLASSNOTAVAILABLE;
}

9-5 CFactory::GetClassObject
CreateInstance CFACTORY.CPP
HRESULT __stdcall CFactory::CreateInstance(IUnknown* pUnknownOuter,
const IID& iid,
void** ppv)
{
// IID IID_IUnknown
if ((pUnknownOuter != NULL) && (iid != IID_IUnknown))
{
return CLASS_E_NOAGGREGATION;
}
//
CUnknown* pNewComponent;
HRESULT hr = m_pFactoryData->CreateInstance(pUnknownOuter, &pNewComponent);
if (FAILED(hr))
{
return hr;
}
// Initialize the component.
hr = pNewComponent->Init();
if (FAILED(hr))
{
// .
pNewComponent->NondelegatingRelease();
return hr;
}
//
hr = pNewComponent->NondelegatingQueryInterface(iid, ppv);
// ,
pNewComponent->NondelegatingRelease();
return hr;
}

9-6 CFactory::CreateInstance
CFactory.
!

CUnknown CFactory
, IUnknown .
QueryInterface, AddRef Release. .
AddRef Release,
QueryInterface. ,
. , 9-7.

153
CMPNT2.H
//
// Cmpnt2.h - 2
//
#include "Iface.h"
#include "CUnknown.h"// IUnknown
///////////////////////////////////////////////////////////
//
// B
//
class CB : public CUnknown, public IY
{
public:
//
static HRESULT CreateInstance(IUnknown* pUnknownOuter,
CUnknown** ppNewComponent);
private:
// IUnknown
DECLARE_IUNKNOWN
// IUnknown
virtual HRESULT __stdcall
NondelegatingQueryInterface(const IID& iid, void** ppv);
// IY
virtual void __stdcall Fy();
//
virtual HRESULT Init();
//
virtual void FinalRelease();
//
CB(IUnknown* pUnknownOuter);
//
~CB();
//
IUnknown* m_pUnknownInner;
// IZ,
IZ* m_pIZ;
};

9-7 , IUnknown, CUnknown


9-7 2 .
. 1 IX . ,
IY IZ, 2. 2 IY 3, ,
, IZ. , 2 , .
9-7 . ,
.
CUnknown, IUnknown.
, CFactory . CFactory
, .
IUnknown DECLARE_IUNKNOWN.
DECLARE_IUNKNOWN IUnknown, CUnknown .
CUnknown AddRef Release,
QueryInterface, , .
NondelegatingQueryInterface .

154
Init
. CUnknown::NondelegatingRelease FinalRelease ,
. ,
. CUnknown::FinalRelease ,
.
2, 9-8.
CMPNT2.CPP
//
// Cmpnt2.cpp - 2
//
#include <objbase.h>
#include
#include
#include
#include

"Iface.h"
"Util.h"
"CUnknown.h"// IUnknown
"Cmpnt2.h"

static inline void trace(char* msg)


{ Util::Trace(" 2", msg, S_OK); }
static inline void trace(char* msg, HRESULT hr)
{ Util::Trace(" 2", msg, hr); }
///////////////////////////////////////////////////////////
//
// IY
//
void __stdcall CB::Fy()
{
trace("Fy");
}
//
//
//
CB::CB(IUnknown* pUnknownOuter)
: CUnknown(pUnknownOuter), m_pUnknownInner(NULL), m_pIZ(NULL)
{
//
}
//
//
//
CB::~CB()
{
trace("");
}
//
// NondelegatingQueryInterface
//
HRESULT __stdcall CB::NondelegatingQueryInterface(const IID& iid, void** ppv)
{
if (iid == IID_IY)
{
return FinishQI(static_cast<IY*>(this), ppv);
}
else if (iid == IID_IZ)
{
return m_pUnknownInner->QueryInterface(iid, ppv);
}
else
{
return CUnknown::NondelegatingQueryInterface(iid, ppv);
}
}

155
//
//
//
HRESULT CB::Init()
{
trace(" 3");
HRESULT hr = CoCreateInstance(CLSID_Component3,
GetOuterUnknown(),
CLSCTX_INPROC_SERVER,
IID_IUnknown,
(void**)&m_pUnknownInner);
if (FAILED(hr))
{
trace(" ", hr);
return E_FAIL;
}
trace(" IZ ");
hr = m_pUnknownInner->QueryInterface(IID_IZ, (void**)&m_pIZ);
if (FAILED(hr))
{
trace(" IZ", hr);
m_pUnknownInner->Release();
m_pUnknownInner = NULL;
return E_FAIL;
}
// - QI
trace(" IZ . .");
GetOuterUnknown()->Release();
return S_OK;
}
//
// FinalRelease Release
//
void CB::FinalRelease()
{
// m_cRef
CUnknown::FinalRelease();
// GetOuterUnknown()->Release Init
GetOuterUnknown()->AddRef();
// ,
//
m_pIZ->Release();
//
// ( , )
if (m_pUnknownInner != NULL)
{
m_pUnknownInner->Release();
}
}
///////////////////////////////////////////////////////////
//
// CFactory
//
HRESULT CB::CreateInstance(IUnknown* pUnknownOuter, CUnknown** ppNewComponent)
{
*ppNewComponent = new CB(pUnknownOuter);
return S_OK;
}

9-8 , CUnknown CFactory

156
NondelegatingQueryInterface
, NondelegatingQueryInterface. ,
QueryInterface . , , . -,
FinishQI, ; . FinishQI
NondeletgatingQueryInterface .
:
HRESULT CUnknown::FinishQI(IUnknown* pI, void** ppv)
{
*ppv = pI;
pI->AddRef();
return S_OK;
}

, IUnknown.
IUnknown , :
HRESULT __stdcall CUnknown::NondelegatingQueryInterface(const IID& iid, void** ppv)
{
// CUnknown IUnknown
if (iid == IID_IUnknown)
{
return FinishQI(reinterpret_cast<IUnknown*>
(static_cast<INondelegatingUnknown*>(this)), ppv);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
}

,
, CUnknown CFactory.
. ,
DLL, :
1.

, .
!" CUnknown, , .
!" DECLARE_IUNKNOWN IUnknown.
!" CUnknown .
!" NondelegatingQueryInterface, , ,
. ,
.
!" ,
Init. , .
!" , - ,
FinalRelease. .
!" CreateInstance.
!" .

2.

1 , DLL.

3.

.
!" CfactoryData g_FactoryDataArray.
!" g_FactoryDataArray
DLL.

!" g_cFactoryDataEntries,
g_FactoryDataArray.
4.

DEF DLL.

157
5.

CUNKNOWN.CPP CFACTORY.CPP.

6.

. , .

smart-, ,
++. , smart-
,
. smart- operator=,
QueryInterface .
smart- , ++
. CUnknown CFactory ,
IUnknown IClassFactory.
, ,
. , , ,
. - .
, , - .

10
EXE
. ,
, , , .
, .
: ,
.
, , .
, .
.
? ,
EXE, DLL. ,
EXE. ,
.
EXE, ,
EXE- .
. ,
, CFactory, ,
. , , ,
.


EXE . .
0x0000ABBA .
, ,
(. 10-1).
EXE- , DLL EXE,
. DLL (in process), EXE
(out of process). EXE ,
. ,
.
1

pFoo

0x0000ABBA

0x00001234

pFoo

0x0000ABBA

0x0BAD0ADD

. 10-1

. 5 , , .
. , , .
, . DLL, :
, .
, .

160
, , .
.
, , :
!" .
!" .
!" , .


, DDE, .
(local procedure call, LPC). LPC
. LPC
,
(remote procedure call, RPC) (. . 10-2).
RPC OSF (Open Software Foundation) DCE (Distributed Computing
Environment) RPC. RPC
. (DCOM),
, RPC .

EXE

RPC? . , , , -,
, .
, ; ,
.

EXE

. 10-2 EXE Win32 LPC


, EXE

EXE . -
.
(marshaling). , marshal ,
. .
, .
.
, , ,
, .
LPC .
, ++.
, , .
, . ,
, , , . ,
, memcpy.
IMarshal.
. -
.
IMarshal, .

161
IMarshal .
Inside OLE.

DLL /
, ,
LPC?
, . , ,
LPC. .
Windows , LPC
Win32. Win32 DLL, LPC
Windows, . ,
, Windows. ,
.
. DLL,
. DLL LPC. COM
(proxy).

, , .
DLL, ,
. ;
DLL, (stub), , .
, (. 10-3).
EXE

DLL

EXE

DLL

. 10-3 DLL .
DLL LPC. DLL

, .
. 10-3 . ,
, .
! !
, EXE . ,
LPC, . IMarshal
. ,
, , ,
.

IDL/MIDL
, , ,
. OpenGL,
. , .
IDL (Interface Definition Language), MIDL
DLL /.
, , . ,
, , ,
. ,

162
. ,
. , , -
.
IDL, UUID RPC, OSF DCE.
++, ,
. IDL, Microsoft
. Microsoft ,
.
IDL
MIDL ( IDL Microsoft). DLL .
, DLL,
! , , .

IDL
LPC,
IDL. , IDL , ,
, . :
(Try to find a work around). IDL , ()
. IDL - MSDN.
, , ,
IDL.
IDL, .
MIDL .
, . ,
IDL, , .

IDL
IDL. SERVER.IDL
. 10.
import unknwn.idl;
// IX
[
object,
uuid(32bb8323-b41b-11cf-a6bb-0080c7b2d682),
helpstring(IX Interface),
pointer_default(unique)
]
interface IX : IUnknown
{
HRESULT FxStringIn([in, string] wchar_t* szIn);
HRESULT FxStringOut([out, string] wchar_t** szOut);
};

++ :
virtual HRESULT __stdcall FxStringIn(wchar_t* szIn);
virtual HRESULT __stdcall FxStringOut(wchar_t** szOut);

, MIDL ++.
([]). , .
. object ,
. IDL Microsoft.
uuid IID .
. , ,
. pointer_default
.
pointer_default
IDL ,
. IDL , .

163
pointer_default MIDL, , .
:
!" ref .
. NULL.
, . ,
(aliases).
!" unique NULL. ,
. .
!" ptr , .
, NULL .
MIDL .
IDL
MIDL (in
out). , MIDL ,
. . out MIDL ,
.
.
:
HRESULT foo([in] int x, [in, out] int* y, [out] int* z);

y , . MIDL ,
.
IDL
, , .
++ 0.
string, MIDL , ,
.
UNICODE, ,
Microsoft Windows 95, UNICODE .
wchar_t. wchar_t OLECHAR
LPOLESTR, .
HRESULT IDL
, , , IX HRESULT. MIDL
, , object, HRESULT.
. ,
- . ,
. , HRESULT.
HRESULT. (
-, , .
Microsoft Visual C++ 5.0
-,
HRESULT.) , HRESULT,
. FxStringOut
. CoTaskMemAlloc.
CoTaskMemFree. CLIENT.CPP . 10
.
wchar_t* szOut = NULL;
HRESULT hr = pIX->FxStringIn(L );
assert(SUCCEEDED(hr));
hr = pIX->FxStringOut(&szOut);
assert(SUCCEEDED(hr));
//
ostrstream sout;

164
sout << FxStringOut :
<< szOut // << wchar_t
<< ends;
trace(sout.str());
//
::CoTaskMemFree(szOut);

CoTaskMemFree.
import IDL
import IDL. UNKNWN.IDL
IDL IUnknown; import ++ #include,
import ,
. OLE (ActiveX) IDL (
INCLUDE ; IDL OLE
).
size_is IDL
, :
// IY
[
object,
uuid(32bb8324-b41b-11cf-a6bb-0080c7b2d682),
helpstring( IY),
pointer_default(unique)
]
interface IY : IUnknown
{
HRESULT FyCount([out] long* sizeArray);
HRESULT FyArrayIn([in] long sizeIn,
[in, size_is(sizeIn)] long arrayIn[]);
HRESULT FyArrayOut([out, in] long* psizeInOut,
[out, size_is(*psizeInOut)] long arrayOut[]);
};

, . size_is.
. ,
. , .
, . ,
?
size_is. FyArrayIn MIDL,
sizeIn. size_is
-. (in-out). - size_is
IY FyArrayOut.
, .
psizeInOut. .
psizeInOut , .
, - ,
. (out)
:
HRESULT FyArrayOut2([in] long sizeIn,
[out, size_is(sizeIn)] long arrayOut[],
[out] long* psizeOut);

CLIENT.CPP . 10. IY
, .
//
long arrayIn[] = { 22, 44, 206, 76, 300, 500 };
long sizeIn = sizeof(arrayIn) / sizeof(arrayIn[0]);

165
HRESULT hr = pIY->FyArrayIn(sizeIn, arrayIn);
assert(SUCCEEDED(hr));
//
//
long sizeOut = 0;
hr = pIY->FyCount(&sizeOut);
assert(SUCCEEDED(hr));
//
long* arrayOut = new long[sizeOut];
//
hr = pIY->FyArrayOut(&sizeOut, arrayOut);
assert(SUCCEEDED(hr));
// ,
ostrstream sout;
sout << FyArray
<< sizeOut
<< : ;
for (int i = 0; i < sizeOut, i++)
{
sout << << arrayOut[i];
}
sout << . << ends;
trace(sout.str());
//
delete [] arrayOut;

, , out
CoTaskMemAlloc. .
IY::FyArrayOut IxxxxENUM::Next, CoTaskMemAlloc.
, CoTaskMemAlloc, .
: ,
StringFromCLSID StringFromGUID2. CoTaskMemFree?
. 6.
IDL
, , .
++ IDL . ,
, :
// IZ
typedef struct
{
double x;
double y;
double z;
} Point3d;
// IZ
[
object,
uuid(32bb8325-b41b-11cf-a6bb-0080c7b2d682),
helpstring( IZ),
pointer_default(unique)
]
interface IZ : IUnknown
{
HRESULT FzStructIn([in] Point3d pt);
HRESULT FzStructOut([in] Point3d* pt);
};

IDL C++. , ,
. MIDL , , ,

166
. void*.
, IUnknown*. IID,
QueryInterface:
HRESULT GetIFace([in] const IID& iid,
[out, iid_is(iid)] IUnknown** ppi);

iid_is MIDL . ,
:
HRESULT GetMyInterface([out] IMyInterface** pIMy);

, IMy2 IMyNewAndVastlyImproved?

MIDL
, IDL, MIDL,
. FOO.IDL,
:
midl foo.idl

, . 10-1.
10-1 , MIDL

FOO.H

( ++), ,
IDL.
/header /h.

FOO_I.C

, GUID, IDL.
/iid.

FOO_P.C

, IDL
. /proxy.

DLLDATA.C

, DLL, .
/dlldata.

IDL library,
. ( ,
.) . 10-4 , MIDL.
, DLL , , .
FOO.H
MIDL

FOO_P.C
FOO_I.C

FOO.IDL

DLLDATA.C
MIDL.EXE

FOO.DLL

make-

FOO.DEF

DLL

REGSVR32.EXE

. 10-4 , MIDL

167

, .
-. make-
: SERVER.DLL SERVER.EXE. ,
,
nmake f makefile

MAKEFILE MAKE-ONE .
\INPROC.
\OUTPROC.
make- MIDL :
midl /h iface.h /iid guids.c /proxy proxy.c server.idl

, MIDL, .
, IFACE.H, SERVER.IDL,
SERVER.IDL, MIDL IFACE.H .
GUID GUID.CPP. GUIDS.C.
, MIDL, , ++.
, . ,
, MIDL IFACE.H. ,
. , ,
.
DLL
DLL /, C,
MIDL. MIDL ,
. - DLL.
DLL DEF. . DEF, , .
LIBRARY
DESCRIPTION
EXPORTS

Proxy.dll
Proxy/Stub DLL
DllGetClassObject
DllCanUnloadNow
GetProxyDllInfo
DllRegisterServer
DllUnregisterServer

@1
@2
@3
@4
@5

PRIVATE
PRIVATE
PRIVATE
PRIVATE
PRIVATE

. ,
MAKE-ONE:
iface.h server.tlb proxy.c guids.c dlldata.c : server.idl
midl /h iface.h /iid guids.c /proxy proxy.c server.idl
!IF $(OUTPROC) !=
dlldata.obj : dlldata.c
cl /c /DWIN32 /DREGISTER_PROXY_DLL dlldata.c
proxy.obj : proxy.c
cl /c /DWIN32 /DREGISTER_PROXY_DLL proxy.c
PROXYSTUBOBJS = dlldata.obj
proxy.obj
guids.obj

\
\

PROXYSTUBLIBS = kernel.lib
rpcndr.lib
rpcns4.lib
rpcrt4.lib
uuid.lib

\
\
\
\

proxy.dll : $(PROXYSTUBOBJS) proxy.def


link /dll /out:proxy.dll /def:proxy.def
$(PROXYSTUBOBJS) $(PROXYSTUBLIBS)
regsvr32 /s proxy.dll

168
DLL /
, make- REGISTER_PROXY_DLL
DLLDATA.C PROXY.C. , DLL /
. , DLL , make- .
, DLL . ,
, . .
DLL / ? . ,
; make- ,
. REGISTER.BAT
.
REGEDIT.EXE :
HKEY_CLASSES_ROOT\
Interface\
{32BB8323-B41B-11CF-A6BB-0080C7B2D682}

GUID IID IX. .


ProxyStubClsid32. CLSID DLL / ;
IX, IY IZ . CLSID HKEY_CLASSES_ROOT\CLSID,
InprocServer32, PROXY.DLL. ,
(. 10-5).
HKEY_CLASSES_ROOT

CLSID

{32BB8323-B41B-11CF-A6BB-0080C7B2D682}
InprocServer32

PSFactoryBuffer
C:\Chap10\proxy.dll

Interface

{32BB8323-B41B-11CF-A6BB-0080C7B2D682}
ProxyStubClsid32

IX

{32BB8323-B41B-11CF-A6BB-0080C7B2D682}

. 10-5 ,
/, MIDL
MIDL
, .


CFactory, .
, , ,
. EXE
DLL. CFactory, DLL,
EXE. CUnknown.
.
_OUTPROC_SERVER_, ,
( ) ( ).
CFactory, .

169


,
. CLSCTX_INPROC_SERVER,
CLSCTX_LOCAL_SERVER.
, ,
, . ,
. , , . ,
, .
, , .
SERVER.EXE start:
C:\>start server

, .
. ,
.


. EXE .
:
DllCanUnloadNow
DllRegisterServer
DllUnregisterServer
DllGetClassObject

. DllCanUnloadNow . EXE, DLL,


. EXE ,
0, . , EXE
DllCanUnloadNow. .
DllRegisterServer DllUnregisterServer . EXE
RegServer UnRegServer. ,
,
CFactory::RegisterAll CFactory::UnregisterAll. , ,
OUTPROC.CPP. ( ,
EXE LocalServer32, InprocServer32.
REGISTRY.CPP.)
, DllClassObject, ,
, DLL.


. 7, , CoCreateInstance CoGetClassObject,
DllGelClassObject. IClassFactory,
. EXE DllGetClassObject,
CoGetClassObject IClassFactory.
, , .
CoGetClassObject ,
, CLSID. ,
EXE.
, . EXE
CoRegisterClassObject. EXE
. CFactory - StartFactories,
CoRegisterClassObject CFactoryData.
.
BOOL CFactory::StartFactories()
{
CFactoryData* pStart = &g_FactoryDataArray[0];
const CFactoryData* pEnd =
&g_FactoryDataArray[g_cFactoryDataEntries 1];

170
for(CFactoryData* pData = pStart; pData <= pEnd; pData++)
{
//
pData->m_pIClassFactory = NULL;
pData->m_dwRegister = NULL;
//
IClassFactory* pIFactory = new CFactory(pData);
//
DWORD dwRegister;
HRESULT hr = ::CoRegisterClassObject(
*pData->m_pCLSID,
static_cast<IUnknown*>(pIFactory),
CLSCTX_LOCAL_SERVER,
REGCLS_MULTIPLEUSE,
&dwRegister);
if (FAILED(hr))
{
pIFactory->Release();
return FALSE;
}
//
pData->m_pIClassFactory = pIFactory;
pData->m_dwRegister = dwRegister;
}
return TRUE;
}

-, CfactoryData.
m_pIClassFactory CLSID, m_pCLSID.
m_dwRegister (cookie)1 .
,
CoRegisterClassObject. CoRegisterClassObject
. CLSID ,
. ;
CoRevokeClassObject. ,
CoRegisterClassObject.
CoRegisterClassObject
,
. .
, EXE
. , EXE SDI (single document
interface ).
, MDI (multiple document interface
) . EXE
SDI, , ,
REGCLS_SINGLEUSE CLSCTX_LOCAL_SERVER.
EXE , , MDI
, REGCLS_MULTI_SEPARATE:
hr = ::CoRegisterClassObject(clsid, pUnknown,
CLSCTX_LOCAL_SERVER,
REGCLS_MULTI_SEPARATE,
&dwRegister);

1
- , cookie , Microsoft. , , ,
Web -cookie. , Microsoft
, - . .
(cookie), .
, cookie , .

171
. , EXE- .
, , EXE .
,
EXE. ,
, . EXE
, , , CLSCTX_LOCAL_SERVER
CLSCTX_INPROG_SERVER:
hr = ::CoRegisterClassObject(clsid, pUnknow,
CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_SERVER,
REGCLS_MULTI_SEPARATE,
&dwRegister);

EXE .
, CLSCTX_INPROC_SERVER
CLSCTX_LOCAL_SERVER REGCLS_MULTIPLEUSE.
:
hr = ::CoRegisterClassObject(clsid, pUnknown,
CLS_LOCAL_SERVER,
REGCLS_MULTIPLEUSE,
&dwRegister);

REGCLS_MULTIPLEUSE

REGCLS_MULTI_SEPARATE.
:
regsvr32 /u server.dll

, .
. .
, Unit CMPNT1.CPP CMPNT2.CPP ,
CLSCTX_INPROC_SERVER,
! , EXE .
REGCLS_MULTIPLEUSE REGCLS_MULTU_SEPARATE CFactory::StartFactories. (,
, CFACTORY.CPP @Multi.)
, . ,
, REGCLS_MULTI_SEPARATE
.

, .
CoRevokeClassObject. StopFactories CFactory
CoRevokeClassObject EXE :
void CFactory::StopFactories()
{
CFactoryData* pStart = &g_FactoryDataArray[0];
const CFactoryData* pEnd =
&g_FactoryDataArray[g_cFactoryDataEntries 1];
for (CFactoryData* pData = pStart; pData <= pEnd; pData++)
{
// .
DWORD dwRegister = pData->m_dwRegister;
if (dwRegister != 0)
{
::CoRevokeClassObject(dwRegister);
}
// .
IClassFactory* pIFactory = pData->m_pIClassFactory;
if (pIfactory != NULL)
{
pIFactory->Release();
}
}
}

172
, CoRevokeClassObject ,
CoRegisterClassObject.

LockServer
DllCanUnloadNow. ,
, . DllCanUnloadNow

CFactory::CanUnloadNow,

CUnknown::s_ActiveComponents. .
, . 7, .
, .
, .
, , ; , , .
,
.
IClassFactory::LockServer, ,
, .
LockServer,
. . DLL . EXE
DLL, EXE DLL. EXE
. EXE, . ,
LockServer, EXE,
. CFactory - CloseExe, WM_QUIT
:
#ifdef _OUTPROC_SERVER_
void CFactory::CloseExe()
{
if (CanUnloadNow() == S_OK)
{
::PostThreadMessage(s_dwThreadID, WM_QUIT, 0,0);
}
}
#else
// CloseExe .
void CFactory::CloseExe() { /**/ }
#endif

, .
, CloseExe LockServer.
HRESULT __stdcall CFactory::LockServer(BOOL block)
{
if (block)
{
::InterlockedIncrement(&s_cServerLocks);
}
else
{
::InterlockedDecrement(&s_cServerLocks);
}
// , .
CloseExe();
return S_OK;
}

CloseExe ; , EXE
, . Cunknown:
CUnknown::~CUnknown()
{
::InterlockedDecrement(&s_cActiveComponents);
// EXE, .
CFactory::CloseExe();
}

173

++ , main. main
. , main.
Windows WinMain. , EXE ,
, main WinMain.
Windows, Windows. ,
Windows.
OUTPROC.CPP.
, .

, ?
. , . ,
, CFactory::s_cServerLocks. ,
, .
, , ? CoGetClassObject
EXE , Embedding. EXE
. Embedding , s_cServerLocks
.
, - . ,
, ,
, . ,
WM_QUIT WM_DESTROY, CanUnloadNow
S_OK. OUTPROC.CPP.


, , ,
. - CLIENT.EXE SERVER.EXE
. , Windows NT 4.0
Windows 95 DCOM. ,
.
, DCOMDCOMCNFG.EXE, Windows NT.
, , ,
.
. 10-2 SERVER.EXE .
10-2 SERVER.EXE

CLIENT, SERVER.EXE PROXY.DLL


nmake-f makefile. ,
. (
Windows 95 Windows NT.)

CLIENT.EXE, SERVER.EXE PROXY.DLL


.
server
/RegServer.

regsvr32 Proxy.dll.

CLIENT.EXE .
,
.

DCOMCNFG.EXE. Inside COM


Chapter 10 Example Component 1 Properties.

174

Location. Run Application On This Computer


Run Application On Following Computer.
,
SERVER.EXE.
Identity -
Interactive User.


Security.

SERVER.EXE, .
CLIENT.EXE 2,
.

#
#

SERVER.EXE .
CLIENT.EXE.

,
. ?

DCOMCNFG.EXE?
DCOMCNFG.EXE REGEDIT.EXE,
. :
HKEY_CLASSES_ROOT\
CLSID\
{0C092C29-882C-11CA-A6BB-0080C7B2D682}

AppID. CLSID
, .
LocalServer32 , , CLSID
. DCOM , ,
. AppID.
AppID, CLSID, GUID. AppID AppID;
CLSID. AppID SERVER.EXE :
HKEY_CLASSES_ROOT\
AppID\
{0C092C29-882C-11CA-A6BB-0080C7B2D682}

AppID . .
RemoteServerName, , , RunAs,
DCOM, . . 10-6.
, AppID .
:
HKEY_CLASSES_ROOT\
AppID\
server.exe

, AppID.

?
, , . DCOM
, CoGetClassObject.
, . CoGetClassObject .
CLSID .
CLSCTX_REMOTE_SERVER, CoGetClassObject ,
AppID. RemoteServerName.
, CoGetClassObject . .

175
HKEY_CLASSES_ROOT

AppID

{0C092C29-882C-11CF-A6BB-0080C7B2D682}

RemoteServerName
"My Remote Server"
RunAs
"Interactive User"

server.exe

AppID
{0C092C29-882C-11CF-A6BB-0080C7B2D682}

CLSID
{0C092C29-882C-11CF-A6BB0080C7B2D682}

AppID
{0C092C29-882C-11CF-A6BB-0080C7B2D682}

. 10-6 AppID.

DCOM
, , ,
, . CoCreateInstance
CoCreateInstanceEx CoGetObject.
CoCreateInstanceEx :
// .
COSERVERINFO ServerInfo;
// .
memset(&ServerInfo, 0, sizeof(ServerInfo));
// .
ServerInfo.pwszName = LMyRemoveServer;
// MULTI_QI .
MULTI_QI mqi[3];
mqi[0].pIID = IIDX_IX; // [in] IID
mqi[0].pItf = NULL; // [out]
mqi[0].hr = S_OK; // [out] QI
mqi[1].pIID = IIDX_IY;
mqi[1].pItf = NULL;
mqi[1].hr = S_OK;
mqi[2].pIID = IIDX_IZ;
mqi[2].pItf = NULL;
mqi[2].hr = S_OK;
HRESULT hr = CoCreateInstanceEx(CLSID_Component1,
NULL,
CLSCTX_REMOTE_SERVER,
&ServerInfo,
3, //
&mqi);

CoCreateInstanceEx CoCreateInstance ,
COMSERVERINFO, .
CoCreateInstanceEx MULTI_QI.
MUTI_QI
QueryInterface . QueryInterface
. ,
.
, QueryInterface.

176
QueryInterface DCOM MULTI_QI.
,
.
IX,IY IZ . CoCreateInstanceEx
S_OK, , MULTI_QI.
E_NOINTERFACE, . ,
, CO_S_NOTALLINTERFACES.
, , hr MULTI_QI.
pItf.
, CoCreateInstanceEx
ImultiQI. :
interface IMultiQI : IUnknown
{
virtual HRESULT __stdcall QueryMultipleInterfaces
(ULONG interfaces,
MULTI_QI* pMQUIs);
};

, IMultiQI .
.
CoCreateInstance Windows 95

_WIN32_DCOM

_WIN32_WINNT >= 0x0400,

CSLCTX_ALL CLSCTX_SERVER CLSCTX_REMOTE_SERVER


Windows 95, DCOM.
Windows 95 Windows NT 3.51, , .
DCOM
, DCOM, , OLE32.DLL
. OLE32.DLL , :
if (GetProcAddress(GetModuleHandle(OLE32), CoInitializeEx) != NULL)
{
// .
}

OLE32.DLL , :
hmodOLE32 = LoadLibrary(OLE32.DLL);
if (GetProcAddress(hmodOLE32, CoInitializeEx) != NULL)
{
// .
}

, , , DCOM:
HKEY hKEY;
LONG lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
SOFTWARE\\Microsoft\\Ole,
0,
KEY_ALL_ACCESS,
&hKey);
assert(lResult == ERROR_SUCCESS);
char rgch[2];
DWORD cb = sizeof(rgch);

177
LResult = RegQueryValueEx(hKey,
TEXT(EnableDCOM),
0, NULL, rgch, &cb);
assert(lResult == ERROR_SUCCESS);
lResult = RegCloseKey(hKey);
assert(lResult == ERROR_SUCCESS);
if (rgch[0] == y || rgch[0] == Y)
{
// DCOM
}

!
(, MIDL), . IDL,
MIDL
. DCOM
.
, . - ,
. , , .

11


, .
, : .
, . , ,
: . ,
. ,
.
, .
.
( OLE ) .
, Microsoft Word Microsoft Excel,
Visual Basic Java.
,
.
.
, ++
. , , ,
.
, . (Automation server)
, IDispatch. (Automation Controller)
, IDispatch.
.
IDispatch .
IDispatch, , Visual Basic
, Microsoft Word Microsoft Excel.
Visual Basic Visual Basic for Applications Microsoft Office. Visual Basic for
Applications Visual Basic Scripting Edition (VBScript)
Web. 5.0 Microsoft Developer Studio VBScript
.
, ,
IDispatch. , IDispatch ( , )
, . - ,
. : IDispatch, disp-, ,
, IDL, VARIANT, BSTR . ,
++.
, ; ,
IDispatch .


IDispatch ? , IDispatch
.
, ,
, IDispatch.

180
IDispatch, ,
; ( ).


, .
, , .
. ,
? ,
.
.
. :
pIX->FxStringOut(msg);

(*(pIX->pvtbl[IndexOfFxStringOut]))(pIX, msg);

pvtbl ytbl , IndexOfFxStringOut


FxStringOut . ,
, .
.
, .
vtbl? , ++
.
, : ProgID
, , . ,
. IDispatch.

IDispatch, , *
, IDipatch . IDipatch IDL,
OAIDL.IDL, :
interface IDispatch : IUnknown
{
HRESULT GetTypeInfoCount([out] UINT * pctinfo);
HRESULT GetTypeInfo([in] UINT iTInfo,
[in] LCID lcid,
[out] ItypeInfo ** ppTInfo);
HRESULT GetIDsOfNames(
[in] REFIID riid,
[in, size_is(cNames)] LPOLESTR * rgszNames,
[in] UINT cNames,
[in] LCID lcid,
[out, size_is(cNames)] DISPID * rgDispId);
HRESULT Invoke([in] DISPID dispIdMember,
[in] REFIID riid,
[in] LCID lcid,
[in] WORD wFlags,
[in, out] DISPPARAMS * pDispParams,
[out] VARIANT * pVarResult,
[out] EXCEPINFO * pExcepInfo,
[out] UINT * puArgErr);
};

GetIDsOfNames Invoke.
, DISPID. DISPID GUID,
(LONG), . DISPID ( IDipatch).
IDipatch IID ( DIID).

IDispatch, You Dispatch, We Dispatch. . .

181
DISPID - Invoke.
DISPID ,
. Invoke .
switch, DISPID.
, MFC.
IDispatch::Invoke .
, IDispatch::Invoke. Microsoft Windows
; IDispatch::Invoke DISPID.
; Invoke
DISPID.
IDispatch::Invoke vtbl. Invoke ,
. vtbl ,
. vtbl ++, Invoke
. ++ vtbl ,
. ++ vtbl ,
. , Invoke,
.
Disp-
IDispatch::Invoke vtbl. . ,
IDispatch::Invoke, (dispatch interface) ,
, disp- (dispinterface). ,
, QueryInterface, AddRef Release.
, ,
. IDispatch::Invoke ,
. , ,
Invoke, , .
. 11-1 .
IDispatch vtbl. disp-. disp DISPID, IDispatch::Invoke.
Invoke GetIDsOfNames: ,
DISPID. . disp- GetIDsOfNames ,
-.
IDispatch
IDispatch*
pIDispatch

pVtbl

Disp-
DISPID

&QueryInterface
&AddRef
&Release

GetDsOfNames

&GetTypeInfoCount

"Foo"

"Bar"

"FooBar"

DISPID

&GetTypeInfo
&GetDsOfNames
&Invoke

Invoke

&Foo

&Bar

&FooBar

. 11-1. Disp- IDispatch


. IDispatch::Invoke.
, IDispatch::Invoke (. 11-2).

. 11-2 disp- .
, . 11-3, , , IDispatch::Invoke,
IUnknown, IDispatch. , (dual
interface). disp-, , Invoke,
vtbl.

182
IDispatch
IDispatch*
pIDispatch

pVtbl

Disp-
DISPID

&QueryInterface
&AddRef
&Release

GetDsOfNames

&GetTypeInfoCount
&GetTypeInfo

"Foo"

"Bar"

"FooBar"

FooBar

&GetDsOfNames
&Invoke

pVtbr

Invoke

&Foo
&Bar
&FooBar

. 11-2 IDispatch::Invoke .
FooBar
IDispatch
IDispatch*
pIDispatch

pVtbl

Disp-
DISPID

&QueryInterface
&AddRef
&Release

GetDsOfNames

&GetTypeInfoCount

"Foo"

"Bar"

"FooBar"

&GetTypeInfo
&GetDsOfNames
&Invoke

Invoke

&Foo
&Bar
&FooBar

. 11-3. , IDispatch.
Invoke, vtbl.
disp-.
++ vtbl; ++, .
- ,
, Invoke vtbl. Visual Basic
disp-, vtbl. Visual Basic Object,
disp-:
Dim doc As Object
Set doc = Application.ActiveDocument
doc.Activate

, Visual Basic vtbl:


Dim doc As Document
Set doc = Application.ActiveDocument
Doc.Activate

- , , , . ,
, , . Visual Basic, .
, ++, .
.
, disp-
, , disp- ++.

183

IDispatch
Visual Basic:
Dim Cmpnt As Object
Set Cmpnt = CreateObject(InsideCOM.Chap11.Cmpnt11)
Cmpnt.Fx

Fx IDispatch,
. ++. -,
ProgID. ( . 6.) ,
DCLIENT.CPP ( ), ,
ProgID. ( .)
// OLE.
HRESULT hr = OleInitialize(NULL);
// CLSID .
wchar_t progid[] = LInsideCOM.Chap11;
CLSID clsid;
hr = ::CLSIDFromProgID(progid, &clsid);
// .
IDispatch* pIDispatch = NULL;
hr = ::CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,
IID_IDispatch, (void**)&pIDispatch);

QueryInterface, CoCreateInstance IDispatch. ,


, DISPID Fx. IDispatch::GetIDsOfNames
DISPID:
DISPID dispid;
OLECHAR* name = LFx;
pIDispatch->GetIDsOfNames(
IID_NULL,
&name,
1,
GetUserDefaultLCID(),
&dispid);

//
//
//
//
//

IID_NULL



DISPID , .
DISPID , .
DISPID Fx, , DISPID IDispatch::Invoke,
. Invoke. Fx
:
// Fx
DISPPARAMS dispparamsNoArgs = {
NULL,
NULL,
0,
//
0,
//
};
// Invoke
pIDispatch->Invoke(dispid,
IID_NULL,
GetUserDefultLCID(),
DISPATCH_METHOD,
&dispparamsNoArgs,
NULL,
NULL,
NULL);

//
//
//
//
//
//
//
//

DISPID
IID_NULL

- .
Fx. .
IDispatch, . IDispatch OAIDL.IDL.
IDispatch .
Invoke. ,
.

184
,
, . ProgID
CLSIDFromProgID GetIDsOfNames. Invoke .
Invoke , .
. . IDispatch::Invoke
. , Invoke ,
. , , VARIANT.
disp-, IDispatch::Invoke.

Invoke
Invoke . .
DISPID , .
IID_NULL. .
, .

. , ++ Win32 API
Get Set. , , SetVisible ,
GetVisible :
if (pIWindow->GetVisible() == FALSE)
{
pIWindow->SetVsible(TRUE);
}

Visual Basic Get Set . Visual Basic


. Visual Basic (properties).
Get/Set, Visual Basic .
:
VB
If Window.Visible = False Then
Window.Visible = True
End If

IDL propget propput , .


:
[
object,
uuid(D15B6E20-0978-11D0-A6BB-0080C7B2D682),
pointer_default(unique),
dual
]
interface IWindow : IDispatch
{
...
[propput]
HRESULT Visible([in] VARIANT_BOOL bVisible);
[propget]
HRESULT Visible([out, retval] VARIANT_BOOL* pbVisible);
...
}

Visible. , propput,
. propget,
. . MIDL propget propput
, get_ put_. , ++
:
VARIANT_BOOL vb;
get_Visible(&vb);
{
put_Visible(VARIANT_TRUE);
}

185
, , , ++, disp-.
Visual Basic, ++.
Visual Basic Java.
. ,
. , VARIANT_TRUE 0xFFFF.
, , IDispatch::Invoke.
, Visible, : ,
, ,
. DISPID,
-. , Invoke , .
:
DISPATCH_METHOD
DISPATCH_PROPERTGET
DISPATCH_PROPERTYPUT
DISPATCH_PROPERTYPUTREF

disp-
, ? IDispatch::Invoke .
. Invoke Visible True.
, , Invoke. ,
True Visible.
DISPPARAMS, :
typedef struct tagDISPPARAMS {
VARIANTARG* rgvarg;
DISPID* rgdispidNamedArgs;
unsigned int cArgs;
unsigned int cNamedArgs;
} DISPPARAMS;

//
//
//
//


DISPID

Visual Basic disp- .


,
. ++,
, . rgdispidNamedArgs
NULL, cNamedArgs 0.
(rgvarg) DISPPARAMS . cArgs
. VARIANTARG,
, , .
disp- ,
VARIANTARG ( vtbl ,
Invoke).
VARIANTARG , VARIANT. IDL OAIDL.IDL
VARIANT:
typedef struct tagVARIANT {
VARTYPE vt;
unsigned short wReserved1;
unsigned short wReserved2;
unsigned short wReserved3;
union {
Byte
Short
long
float
double
VARIANT_BOOL
SCODE
CY
DATE
BSTR
DECIMAL
IUnknown
IDispatch
SAFEARRAY

bVal;
iVal;
lVal;
fltVal;
dblVal;
boolVal;
scode;
cyVal;
date;
bstrVal;
FAR* pdecVal
FAR* punkVal;
FAR* pdispVal;
FAR* parray;

//
//
//
//
//
//
//
//
//
//
//
//
//
//

VT_UI1.
VT_I2.
VT_I4.
VT_R4.
VT_R8.
VT_BOOL.
VT_ERROR.
VT_CY.
VT_DATE.
VT_BSTR.
VT_BYREF|VT_DECIMAL.
VT_UNKNOWN.
VT_DISPATCH.
VT_ARRAY|*.

186
Byte
short
long
float
double
VARIANT_BOOL
SCODE
CY
DATE
BSTR
IUnknown
IDispatch
SAFEARRAY
VARIANT
void
char
unsigned short
unsigned long
int
unsigned int
char FAR *
unsigned short FAR *
unsigned long FAR *
int FAR *
unsigned int FAR *

FAR* pbVal;
FAR* piVal;
FAR* plVal;
FAR* pfltVal;
FAR* pdblVal;
FAR* pboolVal;
FAR* pscode;
FAR* pcyVal;
FAR* pdate;
FAR* pbstrVal;
FAR* FAR* ppunkVal;
FAR* FAR* ppdispVal;
FAR* FAR* pparray;
FAR* pvarVal;
FAR* byref;
cVal;
uiVal;
ulVal;
intVal;
uintVal;
pcVal;
puiVal;
pulVal;
pintVal;
puintVal;

// VT_BYREF|VT_UI1.
// VT_BYREF|VT_I2.
// VT_BYREF|VT_I4.
// VT_BYREF|VT_R4.
// VT_BYREF|VT_R8.
// VT_BYREF|VT_BOOL.
// VT_BYREF|VT_ERROR.
// VT_BYREF|VT_CY.
// VT_BYREF|VT_DATE.
// VT_BYREF|VT_BSTR.
// VT_BYREF|VT_UNKNOWN.
// VT_BYREF|VT_DISPATCH.
// VT_ARRAY|*.
// VT_BYREF|VT_VARIANT.
// Generic ByRef.
// VT_I1.
// VT_UI2.
// VT_UI4.
// VT_INT.
// VT_UINT.
// VT_BYREF|VT_I1.
// VT_BYREF|VT_UI2.
// VT_BYREF|VT_UI4.
// VT_BYREF|VT_INT.
//VT_BYREF|VT_UINT.

};
};

, VARIANT (union) . VARIANT


Visual Basic .
, Visual Basic . ,
. , , , disp-
, VARIANT. Invoke.

, pVarResult VARIANT,
( propget), Invoke. NULL ,
, propput propputref.

IDispatch::Invoke EXCEPINFO.
, Invoke, ( ),
. EXCEPINFO ,
C++.
EXCEPINFO. BSTR ,
.
typedef struct tagEXCEPINFO {
WORD wCode;
WORD wReserved;
BSTR bstrSource;
BSTR bstrDescription;
BSTR bstrHelpFile;
DWORD dwHelpContext;
ULONG pvReserved;
ULONG pfnDefferedFillIn;
SCODE scode;
} EXCEPINFO;

//
//
//
//
//

//
//

, , (wCode),
(scode), .
EXCEPINFO:
EXCEPINFO excepinfo;
HRESULT hr = pIDispatch->Invoke(..., &excepinfo);
if (FAILED(hr))
{

187
// Invoke
if (hr == DISP_E_EXCEPTION)
{
// .
// EXCEPTINFO.
if (excepinfo.pfnDefferedFillIn != NULL)
{
// EXCEPTINFO
(*(excepinfo.pfnDefferedFillIn)(&excepinfo);
}
strstream sout;
sout << :
<< endl
<< :
<< excepinfo.bstrSource << endl
<< :
<< excepinfo.bstrDescription
<< ends;
trace(sout.str());
}
}


IDispatch::Invoke DISP_E_PARAMNOTFOUND,
DISP_E_TYPEMISMATCH, , ,
puArgErr.
, Invoke,
disp-. VARIANT, ,
VARIANT: BSTR SAFEARRAY.

, IX.
. Microsoft Visual C++ :
nmake f makefile

.
IX SERVER.IDL :
// Interface IX
[
object,
uuid(32BB8326-B41B-11CF-A6BB-0080C7B2D682),
helpstring(" IX"),
pointer_default(unique),
dual,
oleautomation
]
interface IX : IDispatch
{
import "oaidl.idl";
HRESULT
HRESULT
HRESULT
HRESULT
};

Fx();
FxStringIn([in] BSTR bstrIn);
FxStringOut([out, retval] BSTR* pbstrOut);
FxFakeError();

. , CLIENT.CPP,
vtbl, . DCLIENT.CPP
disp-. , Fx.
FxStringIn. :
trace(" DispID \"FxStringIn\".");
name = L"FxStringIn";
hr = pIDispatch->GetIDsOfNames(IID_NULL,
&name,
1,
GetUserDefaultLCID(),

188
&dispid);
//
wchar_t wszIn[] = L" ";
// Unicode BSTR
BSTR bstrIn;
bstrIn = ::SysAllocString(wszIn);
//
// VARIANT
VARIANTARG varg;
::VariantInit(&varg);// VARIANT.
varg.vt = VT_BSTR;
// VARIANT
varg.bstrVal = bstrIn;
// VARIANT
// DISPPARAMS
DISPPARAMS param;
param.cArgs = 1;
//
param.rgvarg = &varg;
//
param.cNamedArgs = 0;
//
param.rgdispidNamedArgs = NULL;
trace(" \"FxStringIn\".");
hr = pIDispatch->Invoke(dispid,
IID_NULL,
GetUserDefaultLCID(),
DISPATCH_METHOD,
&param,
NULL,
NULL,
NULL);
//
::SysFreeString(bstrIn);

VARIANTARG DISPPARAMS . ,
, Invoke.
MFC. , ClassWizard disp- - C++.
++ ,
, Invoke.
VARIANT.
BSTR SAFEARRAY.

VARIANT
, VARIANT ( VARIANTARG).
, . , VARIANT
VariantInit. vt VT_EMPTY.
VariantInit vt , VARIANT.
BSTR bstrVal.

++
. ,
.
. , , ,
.
, , Visual Basic ,
C++. , ,
Visual Basic . VARIANT.
Visual Basic :
Dim Bullwinkle As Object
Set Bullwinkle = CreateObject(TalkingMoose)

189
Bullwinkle.PullFromHat 1, Topolino

Visual Basic Bullwinkle , , IDispatch.


Bullwinkle IDispatch, Visual Basic DISPID PullFromHat
IDispatch::GetIDsOfNames. PullFromHat.
,
++. .
Visual Basic , (
). , ,
VARIANT. Visual Basic ,
long, BSTR. Invoke.
, , ,
. , , ,
, . VARIANT
,
. Smalltalk, ,
++.
,
.
,
.

disp- ,
.
PullFromHat . Visual Basic , long BSTR.
, long, double. Disp-
. , disp-
BSTR BSTR. , , IDL :
[propput] HRESULT Title([in] BSTR bstrTitle);

Visual Basic:
component.Title = 100

100 BSTR
(title). , , :
[propput] HRESULT Age([in] short sAge);

Visual Basic:
component.Age = 16

, . ,
. , , .
- , - .
VariantChangeType, :
HRESULT VariantChangeType(
VARIANTARG*
VARIANTARG*
unsigned short
VARTYPE
}

pVarDest,
pVarSrc,
wFlags,
vtNew

//
//
//

. , VARIANT
double VariantChangeType:
BOOL VariantToDouble(VARIANTARG* pvarSrc, double dp)
{
VARIANTARG varDest;
VariantInit(&varDest);
HRESULT hr = VariantChangeType(&varDest,
pvarSrc,
0, VT_R8);

190
if (FAILED(hr))
{
return FALSE;
}
*pd = varDest.dblVal;
return TRUE;
}


disp- .
, VARIANT vt, VT_ERROR, scode,
DISP_E_PARAMNOTFOUND.
.
BSTR.

BSTR
BSTR, Basic STRing Binary STRing ( , )
Unicode. BSTR . -, BSTR
. , (. 114). , BSTR :
BSTR bstr = L ?;

//

. API Win32
SysAllocString:
wchar_t wsz[] = L ;
BSTR bstr;
bstr = SysAllocString(wsz);
BSTR

Unicode
'a' 'b' 'c' '\0' 'd' 'd' 'f'

'\0'

'A'

'B'

'X'

'Y'

'Z'

'\0'

. 11-4 , BSTR
BSTR SysFreeString. BSTR
wchar_t ; , BSTR wchar_t. BSTR
\0. , ,
\0, .

SAFEARRAY
, disp-, SAFEARRAY.
*, , . OAIDL.IDL:
typedef struct tagSAFEARRAY {
unsigned short cDims;
//
unsigned short fFeatures;
unsigned long cbElements;
//
unsigned long clocks;
//
BYTE* pvData;
//
[size_is(cDims) SAFEARRAYBOUND rgsabound[];
} SAFEARRAY;
typedef struct tagSAFEARRAYBOUND {
ULONG cElements;
//
LONG lLBound;
//
} SAFEARRAYBOUND;

fFeatures , SAFEARRAY. :

. ..

191
FADF_BSTR

BSTR

FAFD_UNKNOWN

IUnknown*

FADF_DISPATCH

IDispatch*

FADF_VARIANT

VARIANT

, :
FADF_AUTO

FADF_STATIC

FADF_EMBEDDED

FADF_FIXEDSIZE

OLEAUT32.DLL
SAFEARRAY. SafeArray.
.
, VARIANT,
DISPPARAMS, IDispatch::Invoke,
.
C++.


, Visual Basic ++ disp-,
, . ,
, , . ,
Visual Basic , , .
VARIANT
.
, .
++ ; ,
, .
++,
. (type library) ,
, , , ,
. ++.
IDL, . -
, , .
.
Visual Basic disp-.
, Visual Basic vtbl .
vtbl , .
, ,
, . ,
Visual Basic, .
, ?


CreateTypeLib . CreateTypeLib
IcreateTypeLib, .
- ; IDL
MIDL. . 10 IDL MIDL DLL
/, .
ODL MkTypLib
MIDL .
IDL ODL. ODL
MkTypLib. ODL IDL, ,

192
. ,
, . , IDL MIDL Windows NT 4.0
. ODL MkTypLib
.
library
IDL library. , ,
, library,
. IDL . 11 11-1. ,
GUID, helpstring.
SERVER.IDL
//
// Server.idl IDL Server.dll
//
// MIDL
// (Server.tlb) .
//
// IX
[
object,
uuid(32BB8326-B41B-11CF-A6BB-0080C7B2D682),
helpstring(" IX"),
pointer_default(unique),
dual,
oleautomation
]
interface IX : IDispatch
{
import "oaidl.idl";
HRESULT
HRESULT
HRESULT
HRESULT
};

Fx();
FxStringIn([in] BSTR bstrIn);
FxStringOut([out, retval] BSTR* pbstrOut);
FxFakeError();

//
//
//
[
uuid(D3011EE1-B997-11CF-A6BB-0080C7B2D682),
version(1.0),
helpstring(" COM, 11 1.0 ")
]
library ServerLib
{
importlib("stdole32.tlb");
//
[
uuid(0C092C2C-882C-11CF-A6BB-0080C7B2D682),
helpstring(" ")
]
coclass Component
{
[default] interface IX;
};
};

11-1 IDL, SERVER.TLB


coclass ; Component IX.
MIDL , Component IX. Component
, coclass library. IX
, library.

193
MIDL IDL library, .
. 10 , MIDL SERVER.TLB,
.

,
EXE DLL . ,
.


. . ,
, LoadRegTypeLib,
Windows. , LoadTypeLib,
, LoadTypeLibFromResource,
EXE DLL. LoadTypeLib .
, (. PSS ID Number Q131055).
, LoadTypeLib RegisterTypeLib.
11-2.
CMPNT.CPP
HRESULT CA::Init()
{
HRESULT hr;
// TypeInfo,
if (m_pITypeInfo == NULL)
{
ITypeLib* pITypeLib = NULL;
hr = ::LoadRegTypeLib(LIBID_ServerLib,
1, 0,
//
0x00,
&pITypeLib);
if (FAILED(hr))
{
//
hr = ::LoadTypeLib(wszTypeLibFullName, &pITypeLib);
if(FAILED(hr))
{
trace(" LoadTypeLib ", hr);
return hr;
}
// ,
hr = RegisterTypeLib(pITypeLib, wszTypeLibFullName, NULL);
if(FAILED(hr))
{
trace(" RegisterTypeLib ", hr);
return hr;
}
}
//
hr = pITypeLib->GetTypeInfoOfGuid(IID_IX, &m_pITypeInfo);
pITypeLib->Release();
if (FAILED(hr))
{
trace(" GetTypeInfoOfGuid ", hr);
return hr;
}
}
return S_OK;
}

11-2 ,

194
. LoadTypeLib
ItypeLib, .
. , ITypeLib::GetTypeInfo
CLSID IID, ItypeInfo .
ItypeInfo ,
, , , .. ++
, , ,
IDispatch. ITypeInfo IDispatch .
, .. ,
. Visual Basic,
Object Browser.
. OleView .
OleView ,
IDL/ODL. .


- , .
, . ,
. , .
REGEDIT.EXE HKEY_CLASSES_ROOT\TypeLib. LIBID,
GUID, . GUID
, , . 11-5.
HKEY_CLASSES_ROOT

TypeLib

{D3011EE1-B997-11CF-A6BB-0080C7B2D682}
Inside COM Chapter 11 1.0
Type Library

1.0
0

Win32

C:\CHAP11\SERVER.TLB

FLAGS

HELPDIR

C:\CHAP11

. 11-5 ,
:
. TypeLib GUID CLSID
. , LIBID:
HKEY_CLASSES_ROOT\
CLSID\
{0C092C29-882C-11CF-A6BB-0080C7B2D682}\
TypeLib

TypeLib .
, IDispatch.

IDispatch
, IDispatch , . MFC
. MFC .
IDispatch.
GetIDsOfNames Invoke ITypeInfo.

195
, ITypeInfo .
ITypeLib::GetTypeInfoOfGuid, IID . GetTypeInfoOfGuid
ITypeInfo, IDispatch.
IDispatch ( CMPNT.CPP ):
HRESULT __stdcall CA::GetTypeInfoCount(UINT* pCountTypeInfo)
{
*pCountTypeInfo = 1;
return S_OK;
}
HRESULT __stdcall CA::GetTypeInfo(
UINT iTypeInfo,
LCID,
//
ITypeInfo** ppITypeInfo)
{
*ppITypeInfo = NULL;
if(iTypeInfo != 0)
{
return DISP_E_BADINDEX ;
}
// AddRef
m_pITypeInfo->AddRef();
*ppITypeInfo = m_pITypeInfo;
return S_OK;
}
HRESULT __stdcall CA::GetIDsOfNames(
const IID& iid,
OLECHAR** arrayNames,
UINT countNames,
LCID,
//
DISPID* arrayDispIDs)
{
if (iid != IID_NULL)
{
return DISP_E_UNKNOWNINTERFACE;
}
HRESULT hr = m_pITypeInfo->GetIDsOfNames(arrayNames,
countNames,
arrayDispIDs);
return hr;
}
HRESULT __stdcall CA::Invoke(
DISPID dispidMember,
const IID& iid,
LCID,
//
WORD wFlags,
DISPPARAMS* pDispParams,
VARIANT* pvarResult,
EXCEPINFO* pExcepInfo,
UINT* pArgErr)
{
if (iid != IID_NULL)
{
return DISP_E_UNKNOWNINTERFACE;
}
::SetErrorInfo(0, NULL);
HRESULT hr = m_pITypeInfo->Invoke(
static_cast<IDispatch*>(this),
dispidMember, wFlags, pDispParams,
pvarResult, pExcepInfo, pArgErr);
return hr;
}

196
, ? : ,
. , . ,
LCID, Invoke.


, IDispatch::Invoke,
EXCEPINFO. ITypeInfo::Invoke ,
:
1.

ISupportErrorInfo -:
// ISupportErrorInfo
virtual HRESULT __stdcall InterfaceSupportsErrorInfo(const IID& iid)
{
return (iid == IID_IX) ? S_OK : S_FALSE;
}

2.

IDispatch::Invoke SetErrorInfo(0, NULL) ITypeInfo::Invoke.

3.

CreateErrorInfo,
ICreateErrorInfo.

4.

5.

, IErrorInfo SetErrorInfo,
. 0.
ITypeInfo .

. ( CA::FxFakeError,
CMPNT.CPP . 11.)
//
ICreateErrorInfo* pICreateErr;
HRESULT hr = ::CreateErrorInfo(&pICreateErr);
if (FAILED(hr))
{
return E_FAIL;
}
// pICreateErr->SetHelpFile(...);
// pICreateErr->SetHelpContext(...);
pICreateErr->SetSource(L"InsideCOM.Chap11");
pICreateErr->SetDescription(
L" , ");
IErrorInfo* pIErrorInfo = NULL;
hr = pICreateErr->QueryInterface(IID_IErrorInfo,
(void**)&pIErrorInfo);
if (SUCCEEDED(hr))
{
::SetErrorInfo(0L, pIErrorInfo);
pIErrorInfo->Release();
}
pICreateErr->Release();
return E_FAIL;

make- . 11, , DLL /.


, , OLEAUT32.DLL, ,
1. , , IDispatch
, VARIANT. OLEAUT32.DLL
.
, , IX :

, DLL / , MIDL,
, , Windows 95 Windows NT 4.0. MIDL
VARIANT BSTR, . , OLEAUT32.DLL,
.

197
HKEY_CLASSES_ROOT\
Interfaces\
{32BB8326-B41B-11CF-A6BB-0080C7B2D682}\
ProxyStubClsid32

CLSID:
{00020424-0000-0000-C000-000000000046}

CLSID CLSID:
HKEY_CLASSES_ROOT\
CLSID\
{00020424-0000-0000-C000-000000000046}\
InprocServer32

, InprocServer32 OLEAUT32.DLL

?
: . ,
-, , . : vtbl,
disp-. ? :
, . , , ,
.
++,
vtbl . vtbl disp. , ++.
Visual Basic Java, . Visual Basic Java
disp-, vtbl. ++ .
vtbl ,
Visual Basic, ++ (
Visual C++ 5.0).
vtbl .
++ ,
.
,
disp-. .
, , , .
, vtbl 100 disp-. (
.)
, IDispatch::Invoke,
vtbl disp-.
, .

12


30 . Bell 206B-III Jet Ranger 1:32.

.
. , .
, , .
. ,
, , .
. (Ruediger Asche),
Microsoft Developer Network. Windows NT,
GUI. .
.
,
. ,
.
.
. -
.
, .
Web. ,
;
. , ,
.
.
, ,
.
, .

. ; ,
.
MSDN.

COM
COM Win32 .
, API Win32.
, , Win32.
, Win32.

Win32
Win32 : (userinterface threads) (worker threads).
. ,
. ;
.
.

200
. ,
.
, , .. , . ,
, ,
. ,
, .
, , ,
( , , ). Windows,
, .
, . ,
, ,
.


, -.
(apartment thread). (free thread)
. .
. ,
Win32 SDK, , .
.
, ,
, .
, Win32? :
. ,
, (apartment), (apartment threading)
(free threading).

,
(apartment). ,
( ) .
Win32, ,
. . Windows
. 12-1. . , ,
Windows.
. , .
, . 12-1 . .
. 12-2 ,
.
.
, EXE. .

. 12-1 Windows. : ,
,

201

CoInitialize

CoUninitialize

. 12-2 . ,

Windows.
, ,
- , CoInitialize,
CoUninitialize.

, . . 12-3.
, . .
. .
10, OUTPROC.CPP.
.
. . 10 , DLL /,
.
. 12-3 . , .
, , , .
.


CoInitialize

CoInitialize

CoUninitialize

CoUninitialize

. 12-3
. 12-4 . 12-3 ,
.
. -
.
, . ,
, .
() . ,
. ()

202
. , ,
.
.
.
. , . 12-2, ,
.

CoInitialize

CoInitialize

CoUninitialize

CoUninitialize

. 12-4 ,


.
, . ,
. .
.
.
.
, , Windows
. ,
. ,
, .
. , ,
, .
.
.
, ,
. , ,
. .
, , . ,
, ,
.
.


.
, . ,
. ,
. .
.

203
,
. , , .
, :
.
, Microsoft
Windows NT 3.51 Microsoft Windows 95. Windows NT 4.0 Windows 95 DCOM
.
.
.


,
. .
, .
:
!" . .
10.
!" .
!" .
!" .
!" .
!" .
!" .
.
. , ,
.

, - , , ,
, . -
, .
. .

, , ,
, . ,
.
. ,
.
.

, , ,
. .
, .
, .

,
. . ,
, .
. , , .

204

, .
. , ,
, ,
. .
,
Win32. . .
, :
. .
.
, .
, .
, .


, .
. ,
. Windows
.
. (
;
.) :
!" CoInitialize OleInitialize.
!" .
!" .
!" .
!"
DLL.
!" .
.

.
. ,
. ,
.
, , ,
().

,
. ,
. .
.
DLL
,
. DLL,
DllGetClassObject DllCanUnloadNow. DllGetClassObject
. , ,
. ,
.

205

,
, . DllGetClassObject
, ,
, .

. .
, ,
. InterlockedIncrement InterlockedDecrement,
. 4.
,
. , ,
, .
, ,
.
,
. , ,
.


. . 10 DLL
/, .
, DLL.
.
DLL /
. ,
, ,
.


, ?
, .
. ,
. ,
. , .
, ()
, . , ,
.
.
,
. ,
( ). CoCreateInstance,
. IClassFactory::CreateInstance,
. . IClassFactory::CreateInstance
. CreateInstance
, , .
, CreateInstance,
.
API Win32
, , , , .
CoMarshalInterface CoUnMarshalInterface.
, API Win32,
CoMarshalInterThreadInterfaceInStream CoGetInterfaceAndReleaseStream. ( ,
.)
. IX :

206
IStream* pIStream = NULL;
HRESULT hr = CoMarshalInterThreadInterfaceInStream(
IID_IX,
// ID ,
pIX,
// ,
&pIStream); // ,

:
IX* pIXmarshaled;
HRESULT hr = CoGetInterfaceAndReleaseStream(
pIStream,
// ,
IID_IX,
// ID
(void**)&pIXmarshaled);
//

, ? ,
DLL /.


, :
. . ,
, , .
Win32, , .
, .
. .
,
. , Win32
, :
!" .
!" .
!" .
, .
,
, . , . , .
, ,
CSimpleApartment.
CSimpleApartment CClientApartment
CSimpleApartment , .
APART.H APART.CPP CHAP12\APT_THD

.
CSimpleApartment::StartThread

.
CSimpleApartment::CreateComponent CLSID ,
StartThread.
( ). CSimpleApartment .
CSimpleApartment , . CSimpleApartment
. CSimpleApartment::CreateComponent
, .
. CreateComponent ,

CreateComponentOnThread. CSimpleApartment::CreateComponentOnThread ,
. CClientApartment
CreateComponentOnThread,
CoCreateInstance.


. 12-1 , .
, CSimpleApartment::StartThread.

207
12-1

WinMain

CSimpleApartment

CSimpleApartment

InitializeApartment

StartThread

RealThreadProc
ClassThreadProc
CClientApartment::WorkerFunction

CreateComponent

CreateComponentOnThread
CClientApartment::CreateComponentOnThread

CSimpleApartment::StartThread
CLIENT.CPP
CSimpleApartment::StartThread, :

InitializeApartment.

BOOL CSimpleApartment::StartThread(DWORD WaitTime)


{
if (IsThreadStarted())
{
return FALSE;
}
//
m_hThread = ::CreateThread(NULL,
0,
RealThreadProc,
(void*)this,
CREATE_SUSPENDED,
&m_ThreadId);

//
//
//
//
//
//

if (m_hThread == NULL)
{
trace("StartThread ", GetLastError());
return FALSE;
}
trace("StartThread ");
//
m_hCreateComponentEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
if (m_hCreateComponentEvent == NULL)
{
return FALSE;
}
// ,
m_hComponentReadyEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
if (m_hComponentReadyEvent == NULL)
{
return FALSE;
}
trace("StartThread ");
//
m_WaitTime = WaitTime;
// ;
DWORD r = ResumeThread(m_hThread);
assert(r != 0xffffffff);
//
WaitWithMessageLoop(m_hComponentReadyEvent);
return TRUE;
}

208
CSimpleApartment::StartThread ::CreateThread.
. CSimpleApartment::ClassThreadProc,
, m_hComponentReadyEvent ,
, , .
CSimpleApartment::CreateComponent m_hCreateComponentEvent,
CSimpleApartment::CreateComponentOnThread .
CreateComponentOnThread m_hCreateComponentEvent,
CreateComponent.
CSimpleApartment::WaitWithMessageLoop , .
, Windows. ,
, .

.
WaitWithMessageLoop

API
Win32
MsgWaitForMultipleObjects, .
CSimpleApartment::ClassThreadProc
RealThreadProc, ClassThreadProc.
Windows ++, Win32
. ,
ClassThreadProc. ClassThreadProc :
DWORD CSimpleApartment::ClassThreadProc()
{
//
HRESULT hr = CoInitialize(NULL);
if (SUCCEEDED(hr))
{
// ,
SetEvent(m_hComponentReadyEvent);
//
BOOL bContinue = TRUE;
while (bContinue )
{
switch(::MsgWaitForMultipleObjects(
1,
&m_hCreateComponentEvent,
FALSE,
m_WaitTime,
QS_ALLINPUT))
{
//
case WAIT_OBJECT_0:
CreateComponentOnThread();
break;
// Windows
case (WAIT_OBJECT_0 + 1):
MSG msg;
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
{
bContinue = FALSE;
break;
}
DispatchMessage(&msg);
}
break;
//
case WAIT_TIMEOUT:
WorkerFunction();
break;
default:
trace(" ", GetLastError());
}

209
}
// COM
CoUninitialize();
}
//
SetEvent(m_hComponentReadyEvent);
return 0;
}

.
ClassThreadProc . ,
GetMessage/DispatchMessage, ClassThreadProc MsgWaitForMultipleObjects, ,
: m_hCreateComponentEvent, Windows . m_hCreateComponentEvent, MsgWaitForMultipleObjects
ClassThreadProc CreateComponentOnThread. Windows,
PeekMessage/DispatchMessage ( ,
). -, CSimpleApartment::WorkerFunction.
CClientApartment, .
GetMessage/DispatchMessage .
PostThreadMessage. MsgWaitForMultipleObjects
.
CSimpleApartment::CreateComponent
, , .
CSimpleApartment::CreateComponent. :
HRESULT CSimpleApartment::CreateComponent(const CLSID& clsid,
const IID& iid,
IUnknown** ppI)
{
//
m_pIStream = NULL;
m_piid = &iid;
m_pclsid = &clsid;
//
SetEvent(m_hCreateComponentEvent);
//
trace(" ");
if (WaitWithMessageLoop(m_hComponentReadyEvent))
{
trace(" ");
if (FAILED(m_hr))
{
return m_hr;
}

// GetClassFactory?

if (m_pIStream == NULL)
{
return E_FAIL;
}

// ?

trace(" ");
//
HRESULT hr = ::CoGetInterfaceAndReleaseStream(m_pIStream,
iid,
(void**)ppI);
m_pIStream = NULL;
if (FAILED(hr))
{
trace(" CoGetInterfaceAndReleaseStream", hr);
return E_FAIL;
}
return S_OK;
}

210
trace(" ?");
return E_FAIL;
}

CreateComponent . -,
-. -, . -,
. -,
.
CSimpleApartment::CreateComponentOnThread
CreateComponent m_hCreateComponentEvent, ClassThreadProc
CreateComponentOnThread, . -,
CreateComponentOnThread , CreateComponent.
CreateComponentOnThread
. -, :
void CSimpleApartment::CreateComponentOnThread()
{
IUnknown* pI = NULL;
//
m_hr = CreateComponentOnThread(*m_pclsid, *m_piid, &pI);
if (SUCCEEDED(m_hr))
{
trace(" ");
//
HRESULT hr = ::CoMarshalInterThreadInterfaceInStream(*m_piid,
pI,
&m_pIStream);
assert(SUCCEEDED(hr));
// pI
pI->Release();
}
else
{
trace(" CreateComponentOnThread", m_hr);
}
trace(" , ");
SetEvent(m_hComponentReadyEvent);
}

CreateComponentOnThread CoMarshalInterThreadInterfaceInStream
. CreateComponent .

CClientApartment
CClientApartment : CreateComponentOnThread
WorkerFunction. CClientApartment ,
. CreateComponentOnThread, CoCreateInstance:
HRESULT CClientApartment::CreateComponentOnThread(const CLSID& clsid,
const IID& iid,
IUnknown** ppI)
{
HRESULT hr = ::CoCreateInstance(clsid,
NULL,
CLSCTX_INPROC_SERVER,
iid,
(void**)ppI);
if (SUCCEEDED(hr))
{
// IX, WorkerFunction
hr = (*ppI)->QueryInterface(IID_IX, (void**)&m_pIX);
if (FAILED(hr))
{
// ,
(*ppI)->Release();
return E_FAIL;

211
}
}
return hr;
}

CClientApartment::CreateComponentOnThread IX,
WorkerFunction:
void CClientApartment::WorkerFunction()
{
if (m_pIX)
{
m_pIX->Tick();
}
}

CLIENT.CPP
. ,
CSimpleApartment::m_WaitTime, CSimpleApartment::ClassThreadProc CClientApartment::WorkerFunction.
, .
. WM_TIMER, OnTick,
IX::GetCurrentCount .
IX::GetCurrentCount, . WorkerFunction
IX::Tick, , .
.
. ,
.
. ,
.
, , .


, . Win32
, CreateThread, ResumeThread, WaitForMultipleObjects, WaitForSingleObject,
CreateMutex CreateEvent. ,
, ,
. ,
, .
,
. ,
.
, ,
, . ,
. Windows NT 4.0 Windows 95 ,
DCOM. . 10 , ,
. ( OLE32.DLL
CoInitializeEx.)
CoInitializeEx: COINIT_MULTITHREADED,
. ? , ,
, .
, .
, CoInitializeEx COINIT_MULTITHREADED,

OleInitialize

CoInitializeEx

COINIT_APARTMENTTHREADED, OLE
.

212
, .
. ,
, COM.
, .
, . ,
DLL /.
.
CoMarshalInterThreadInterfaceInStream CoGetInterfaceAndReleaseStream.
, .
.
.
.
, ,
. , ,
. , .


.
\CHAP12\FREE_THD ,
. ( ).
. ,
, . , .
()
.
. , .

CSimpleApartment CSimpleFree.
, . , CClientApartment CClientFree.
, CSimpleFree .
CSimpleFree . ,
. CSimpleFree .
CSimpleFree::ClassThreadProc
, CSimpleFree CSimpleApartment,
ClassThreadProc. CoInitialize, CSimpleApartment, CoInitializeEx(0,
COINIT_MULTITHREADED). CoInitializeEx, . -,
_WIN32_WINNT = 0x400 _WIN32_DCOM. , OBJBASE.H
CoInitializeEx. -, ,
CoInitializeEx. :
BOOL CSimpleFree::ClassThreadProc()
{
BOOL bReturn = FALSE;
// CoInitializeEx
typedef HRESULT (__stdcall *FPCOMINITIALIZE)(void*, DWORD);
FPCOMINITIALIZE pCoInitializeEx =
reinterpret_cast<FPCOMINITIALIZE>(
::GetProcAddress(::GetModuleHandle("ole32"), "CoInitializeEx"));
if (pCoInitializeEx == NULL)
{
trace(" DCOM");
SetEvent(m_hComponentReadyEvent);
return FALSE;
}
// COM
HRESULT hr = pCoInitializeEx(0, COINIT_MULTITHREADED);
if (SUCCEEDED(hr))
{
//

213
SetEvent(m_hComponentReadyEvent);
//
HANDLE hEventArray[2] = { m_hCreateComponentEvent,
m_hStopThreadEvent };
//
BOOL bContinue = TRUE;
while (bContinue)
{
switch(::WaitForMultipleObjects(2,
hEventArray,
FALSE,
m_WaitTime))
{
//
case WAIT_OBJECT_0:
CreateComponentOnThread();
break;
//
case (WAIT_OBJECT_0 +1):
bContinue = FALSE;
bReturn = TRUE;
break;
//
case WAIT_TIMEOUT:
WorkerFunction();
break;
default:
trace(" ", GetLastError());
}
}
// COM
CoUninitialize();
}
// ,
SetEvent(m_hComponentReadyEvent);
return bReturn;
}

CSimpleFree , .
MsgWaitForMultipleObjects WaitForMultipleObjects. WM_QUIT
m_hStopThreadEvent.
MsgWaitForMultipleObjects ClassThreadProc, -
CSimpleFree::StartThread CSimpleFree::CreateComponent.
(), ,
.
CSimpleFree CSimpleApartment.
CClientFree
,
, . CClientFree .
CClientFree CClientApartment
. CClientFree CSimpleFree CreateComponentOnThread
WorkerFunction.

CClientFree

ShareUnmarshaledInterfacePointer

UseUnmarshaledInterfacePointer. ( ,
.) , ShareUnmarshaledInterfacePointer,
IX, CClientFree WorkerFunction.
, . ,
UseUnmarshaledInterfacePointer, IX, CClientFree
WorkerFunction. , CLIENT.CPP.

214
InitializeThread CLIENT.CPP .
InitializeApartment .
InitializeThread InitializeThread2. .
, . InitializeThread2
:
BOOL InitializeThread2()
{
if (g_pThread == NULL)
{
return FALSE;
}
//
// WorkerFunction
g_pThread2 = new CClientFree2;
//
if (g_pThread2->StartThread())
{
trace(" ");
// ,
IX* pIX = NULL;
pIX = g_pThread->ShareUnmarshaledInterfacePointer();
assert(pIX != NULL);
//
g_pThread2->UseUnmarshaledInterfacePointer(pIX);
pIX->Release();
return TRUE;
}
else
{
trace(" ");
return FALSE;
}
}

InitializeThread2 CClientFree CClientFree2. CClientFree2 CClientFree


WorkerFunction. :
void CClientFree::WorkerFunction()
{
CSimpleLock Lock(m_hInterfaceMutex);
if (m_pIX)
{
m_pIX->Tick(1);
m_pIX->Left();
}
}
void CClientFree2::WorkerFunction()
{
CSimpleLock Lock(m_hInterfaceMutex);
if (m_pIX)
{
m_pIX->Tick(-1);
m_pIX->Right();
}
}

CSimpleLock . IX::Tick,
. Left Right. ,
. CClientFree . CClientFree2
. InRightHand TRUE, .
, , .

215

.
, . ,
, CsimpleLock:
class CSimpleLock
{
public:
//
CSimpleLock(HANDLE hMutex)
{
m_hMutex = hMutex;
WaitForSingleObject(hMutex, INFINITE);
}
//
~CSimpleLock()
{
ReleaseMutex(m_hMutex);
}
private:
HANDLE m_hMutex;
};

CSimpleLock . ,
. CsimpleLock ,
. CSimpleLock:
HRESULT __stdcall CA::Tick(int delta)
{
CSimpleLock Lock(m_hCountMutex);
m_count += delta;
return S_OK;
}
HRESULT __stdcall CA::Left()
{
CSimpleLock Lock(m_hHandMutex);
m_bRightHand = FALSE;
return S_OK;
}

m_hHandMutex m_hCountMutex.
, , .
, , .
.
, Left, Tick.
,
.


, . , . ,
,
. ,
. ,
. , ; ,
,
. ,
. , .

, . CoCreateFreeThreadedMarshaler
IMarshal, , .
, . ,

216
. CoCreateFreeThreadedMarshaler ,
, , .
CoMarshalInterThreadInterfaceInStream CoGetInterfaceAndReleaseStream.
.
, . QueryInterface,
IMarshal .
HRESULT CA::Init()
{
HRESULT hr = CUnknown::Init();
if (FAILED(hr))
{
return hr;
}
//
m_hCountMutex = CreateMutex(0, FALSE, 0);
if (m_hCountMutex == NULL)
{
return E_FAIL;
}
//
m_hHandMutex = CreateMutex(0, FALSE, 0);
if (m_hHandMutex == NULL)
{
return E_FAIL;
}
//
hr = ::CoCreateFreeThreadedMarshaler(
GetOuterUnknown(),
&m_pIUnknownFreeThreadedMarshaler);
if (FAILED(hr))
{
return E_FAIL;
}
return S_OK;
}
HRESULT __stdcall CA::NondelegatingQueryInterface(const IID& iid, void** ppv)
{
if (iid == IID_IX)
{
return FinishQI(static_cast<IX*>(this), ppv);
}
else if (iid == IID_IMarshal)
{
return m_pIUnknownFreeThreadedMarshaler->QueryInterface(iid, ppv);
}
else
{
return CUnknown::NondelegatingQueryInterface(iid, ppv);
}
}


, , ,
. Win32 SDK apartment () ,
. , ,
. ,
, . ,
Win32 SDK.


, ,
.

217
,
InprocServer32 ThreadingModel. (ThreadingModel ,
!) ThreadingModel : Apartment, Free Both.
, , ,
Apartment. , ,
Free. , , ,
Both. , .
, , . ,
, .

, ,
. ,
. Win32 ,
. .
,
. , ,
. .
, ,
.
CoInitializeEx.
, -
.
.
, ?
. ,
, .
, . ,
.
.
. ,
, , .
,
, .
, ?
.

13

,
(. 13-1). ,
.
: ,
. . . 13-1.
, , , ,
(. . 13-2).
. , ,
, .

. 13-1

. 13-2
. ,

220
, , ,
. -, ,
.

Tangram
,
. .
, , . , ,
. , ; , ,
, . ,
, - . ,
, .
, . Tangram,
Microsoft Windows. Tangram ,
, . , Tangram OLE,
ActiveX COM , .

Tangram
\TANGRAM .
REGISTER.BAT, . ,
.
Tangram ,
:
!" ,
. TangramGdiWorld , TangramGLWorld
. OpenGL ,
TangramGdiWorld.
!" , , ,
. (
, . 10).
Tangram . .
. Shift,
. , ,
!


Tangram
\TANGRAM\SOURCE, .

Tangram . ,
Tangram, Tangram ITangram .
, .
Tangram , GUID Tangram
:
B53313xxx-20C4-11D0-9C6C-00A0C90A632C

Tangram . 13-1.
13-1 Tangram

TangramModel

ITangramModel
ITangramTransform
ITangramPointContainer

TangramGdiVisual

ITangramVisual
ITangramGdiVisual

221

ITangramModelEvent
TangramGdiWorld

ITangramWorld
ITangramGdiWorld
ITangramCanvas

TangramCanvas

ITangramCanvas

, Gdi,
, GL. TangramGdiVisual OpenGL TangramGLVisual.
GDI ,
OpenGL .
, Tangram.
. 13-3.
(, , , .)
EXE-

TangramModel

ITangramModel

pITangramTransform
m_pSelectedVisual

ITangramTransform

m_pWorld
pCanvas
TangramGdiWorld

TangramGdiVisual

m_pModel

ITangramWorld
ITangramGdiWorld
TangramCanvas
ITangramCanvas

ITangramVisual
ITangramGdiVisual
ITangramModelEvent
m_pGdiWorld

. 13-3 Tangram

EXE-
EXE- . EXE
, ++ Win32, MFC,
. .
Tangram*World ITangramWorld, ITangramVisual TangramModel
ITangramModel ITangramTransform.
TangramModel
. TangramModel Tangram*Visual.
TangramModel ITangramModel. Tangram*World Tangram*Visual.
ITangram*World Tangram*Visual ITangram*Visual.
Tangram*World TangramCanvas, ITangramCanvas,
EXE.

TangramModel
TangramModel Tangram. TangramModel,
, , .
ITangramModel ITangramTransform.

222
ITangramModel
ITangramModel , .
20x20 ,
. ,
, , ITangramWorld ITangramVisual.
ITangramTransform
ITangramTransform .
Tangram .
.
IConnectionPointerContainer
COM/ActiveX.
. TangramModel
Tangram*Visual .

TangramGdiVisual TangramGLVisual
TangramModel Tangram*Visual, (visual).
TangramGdiVisual GDI .
TangramGLVisual OpenGL .
ITangramModel TangramModel.
Tangram*Visual TangramModel
. Tangram*Visual :
ITangramVisual, ITangram*Visual ITangramModelEvent.
ITangramVisual
ITangramVisual , ,
. ,
.
ITangramGdiVisual ITangramGLVisual
TangramGdiWorld ITangramGdiVisual
TangramModel. TangramGLWorld ITangramGLVisual
TangramGLVisual TangramModel.
,
. TangramGdiWorld TangramGLWorld ,
, .
20x20, ,
Tangram*World Tangram*Visual.
TangramModel ,
Tangram*World Tangram*Visual . Tangram*World
, Tangram*Visual.
. , ,
, . COM
.
ITangramModelEvent
ITangram*Visual
ITangramModel. ITangramModel ITangramModelEvent.
, , TangramModel ITangramModelEvent::OnChangeModel
, (
). .

TangramGdiWorld TangramGLWorld
Tangram*Visual Tangram*World. Tangram*World
, TangramVisual.

223
. Tangram*World : ITangramWorld, ITangram*World
ITangramCanvas.
ITangramWorld
EXE- Tangram*World
ITangramWorld. EXE Tangram*Visual,
Tangram*World Tangram*Visual.
ITangramGdiWorld ITangramGLWorld
Tangram*Visual
Tangram*World. ,
; 0 ,
, .
.
ITangramCanvas
EXE ITangramCanvas Tangram*World ,
, , .
TangramGdiWorld, TangramGLWorld, .
TangramCanvas, .


, Tangram . ,
.

Tangram*World TangramCanvas, EXE ITangramCanvas.

Tangram. . 13-3, Tangram*World


Tangram*Visual, TangramModel.

Tangram Tangram World. ,
ITangramWorld ITangramCanvas. EXE ,
, ITangramWorld ITangramCanvas.
, .

,
. TangramGLWorld TangramGLVisual TangramGdiWorld TangramGdiVisual
. , -.
,
TangramModel , . EXE
, .
() Tangram,
.

IDL
IDL
. , ,
, . IDL Tangram
. IDL _I.
, MODEL_I.IDL ITangramModel ITangramTransform.

224
coclass library. coclass, ,
IDL, _C.
_I .
. IDL ,
. . , _C
CLSID, _I IID. IID,
_I. , IID_ITangramModel MODEL_I.IDL.
IID_ITangramModel, MODEL_I.H MODEL_I.C.
TangramModel, CLSID_TangramModel.
MODEL_C.IDL. , MODEL_C.H MODEL_C.C. IDL
IDL, ++ .
, MODEL_I.IDL EVENTS_I.IDL. , MODEL_I.H,
EVENTS_I.H.
, _I _C . .
, . , , CLSID,
, _C.

DLLDATA.C
MIDL DLLDATA.C.
DLL /, .
IDL. MIDL
DLLDATA.C, , .
DLLDATA.C, , , .


TangramGdiWorld TangramGdiVisual,
ITangramGdiWorld. TangramGdiVisual
. , (. 13-4). TangramGdiWorld
TangramGdiVisual, TangramGdiWorld.
,
, . , TangramGdiWorld
TangramGdiVisual ITangramGdiVisual, AddRef. ,
TangramGdiWorld ITangramGdiWorld TangramGdiVisual,
AddRef. TangramGdiVisual,
TangramGdiWorld .
TangramGdiWorld

TangramGdiVisual

ITangramGdiVisual

ITangramGdiWorld

m_pGdiWorld

. 13-4 Tangram
TangramGdiWorld ITangramGdiVisual , ,
0. TangramGdiVisual ITangramGdiWorld
TangramGdiWorld, , 0.
, . TangramGdiWorld TangramGdiVisual
, TangramGdiVisual TangramGdiWorld. TangramGdiVisual
, TangramGdiWorld. ,
.
: AddRef,
.

AddRef
. .
TangramGdiVisual. AddRef
ITangramGdiWorld, TangramGdiWorld. TangramGdiVisual ,

225
TangramGdiWorld, , ,
.
, . ,
, (weak reference).
. (string reference) ,
. (. 13.5).
, . ,
, , . TangramGdiVisual
, TangramGdiWorld.
, ,
.
TangramGdiWorld

TangramGdiVisual

ITangramGdiVisual

ITangramGdiWorld

m_pGdiWorld

. 13-5 TangramGdiVisual
TangramGdiWorld. .


( )
. , 0,
.
, (. 13-6).
TangramGdiWorld

TangramGdiVisual

ITangramGdiVisual

ITangramGdiWorld

ILifeTime
m_pGdiWorld

. 13-6 ,
,
0
. , ,
- .
, . IClassFactory::LockServer.
. . 7 10.
IOleContainer::LockContainer IExternalConnection::AddConnection.
.


,
.
. . 13-7. TangramGdiWorld
TangramGdiVisual, TangramGdiWorld.
.
; ,
, .
.
TangramGdiWorld TangramGdiVisual .
TangramGdiVisual TangramGdiWorld .
TangramGdiVisual TangramModel
. .

226
TangramGdiWorld

TangramGdiVisual

ITangramGdiVisual

ITangramGdiWorld

m_pGdiWorld

. 13-7 , ,


, .
.
, . Tangram .
, TangramGdiVisual TangramGdiWorld.

. ,
. ,
.
ActiveX (OLE)
. (connection points).
. ,
. .
(outgoing) , (source). IDL

source.
(

\TANGRAM\SOURCE\MODEL\MODEL_C.IDL.) ,
. ,
.
. . 13-8 TangramModel
ITangramModelEvent, TangramGdiVisual,
, TangramGdiVisual (
.)
. 13-8 TangramModel ITangramModelEvent. ,
ITangramModelEvent , m_pEvents. ,
. . -, ,
. -, . , TangramModel .
.
.
TangramGdiWorld

TangramGdiVisual

m_pITangramVisual

ITangramGdiVisual

ITangramModelEvent

ITangramModelEvent

m_pGdiWorld

. 13-8 , Tangram
IConnectionPointContainer. : FindConnectionPoint
EnumConnectionPoints. IID
. EnumConnectionPoints , ,
. ,
. , , .
, IConnectionPoint.
.

227
. IConnectionPoint::EnumConnections IEnumConnections ,
. ,
.
TangramGdiWorld
m_pITangramVisual

TangramGdiVisual
IConnectionPointContainer

CEnumConnectionPoints
IEnumConnectionPoints

ITangramModelEvent

ConnectionPoint
CEnumConnections

CTangramModelEventSink
ITangramModelEvent

IConnectionPointContainer

IEnumConnections

ConnectionPoint

. 13-9
. 13-9 TangramModel. TangramGdiVisual
IConnectionPointContainer, IConnectionPoint, IID_ITangramModelEvent.
TangramGdiVisual IConnectionPoint::Advise.
, TangramGdiVisual .
TangramModel . new
++, CLSID, Windows. . 13-9
. ,
- . TangramModel ,
, IEnumConnectionPoints.
.
(. 13-9) .
; , .
.

IEnumXXX
.
.
, .
IEnumXXX, Reset, Next, Skip Clone.
IEnumConnectionPoints IEnumConnections. . 6
IEnumCATEGORYINFO.
Next .
, . ,
, Next .
,
.
. AddRef Release
. Next,
AddRef, . Next,
Release.
, ? , , ,
IEnumConnections IEnumConnectionPoints. -,
IConnectionPoint::EnumConnections,
. (- , Advise
Unadvise ), .

228

COM
, .
, .
, OLE, ActiveX, ActiveX .
.
,
.

--!
, . , ++, IUnknown
IClassFactory Windows. ,
, . ,
++ smart-. IDL,
. IDispatch
, ITypeInfo. , ,
.
, , ,
. , .
, . Microsoft
ActiveX, DirectX OLE. ActiveX
. ActiveX .
ActiveX .
ActiveX, DirectX OLE . , ,
. , .
( ,
.) Tangram,
. !

Вам также может понравиться