Академический Документы
Профессиональный Документы
Культура Документы
........................................................................................................................................................................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_
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
wsz
Unicode
?
? , ,
. ,
. ,
.
.
. , .
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/
. ,
,
. ,
, . , .
, ,
.
.
,
. , ,
(. 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(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;
};
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;
}
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;
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();
, 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
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();
}
// DLL
// 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;
}
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).
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}};
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}
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;
. 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
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.
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
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);
, :
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
);
//
//
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);
}
96
. ,
. -, ,
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
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
);
//
//
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;
};
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;
}
,
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();
}
, 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;
};
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);
IPtr NULL:
spIX = NULL;
, , , IPtr .
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;
}
, 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;
}
- 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
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
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;
};
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"
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;
}
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
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
\
\
\
\
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}
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
. 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
regsvr32 Proxy.dll.
CLIENT.EXE .
,
.
174
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
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);
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).
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
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, .
, ++, .
.
, 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);
//
//
//
//
//
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);
}
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
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.
};
};
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,
¶m,
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:
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;
};
};
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.
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;
, 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.
//
//
//
//
//
//
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;
}
}
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 . ,
.
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,
. !