|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule,
3 U' p8 ^; X$ x2 Q+ C4 ?* b: I- P$ X
0 k8 ]1 J V* O* l
5 g3 W2 m: w: B) y+ S///////////////////////////////////////////) a# @4 M4 j' m
//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.0 u0 K$ u+ S% j4 u0 G) C8 x8 c7 p
, M- f3 @ M: z/ Z( Q; j
/ r2 X. ]( \' ~! ]' T#pragma once
) r% x# f# U5 }7 D2 o/ c' b#include <exception>
- v, J! A+ v- r' H2 J" _; g7 j
7 K4 v0 ^0 i3 w/ v( G- s enum TRISTATE{* [7 Y8 q0 W% @, l, |3 S
TRIS_FALSE,! ?' I( I$ w0 J4 W) n% N+ p5 T2 z
TRIS_UNKNOWN,
% j4 R. L0 u3 i$ T; f! T TRIS_TRUE9 Z) B1 r6 E5 s. n; O T H
};
+ V. K' Y0 M" l7 B& f; m8 u
8 V0 h; L: J" {6 o P" D- j0 l4 W8 I* d
enum UPNP_IMPLEMENTATION{ d1 y1 `9 Q& `$ ?
UPNP_IMPL_WINDOWSERVICE = 0,% s0 V, {5 {& T2 ~- w9 s
UPNP_IMPL_MINIUPNPLIB,
" p7 E) N- ^' y* e1 H' @ UPNP_IMPL_NONE /*last*/
8 U: _4 I6 P/ |+ a. R};' `$ j- }5 }& b/ g4 G5 q
* u" V" L ?- i3 ]+ t2 U% N4 f
( c$ A7 i# m" y6 m
4 D% C+ H! i# E
' p5 @; D. @3 P
class CUPnPImpl
- f# y H p; W{
4 y7 X6 L) h# h0 @0 Spublic:; e# p/ k0 G/ o
CUPnPImpl();5 S, G# k: A. w, u* O
virtual ~CUPnPImpl();
# E' c; n3 f6 m struct UPnPError : std::exception {};& q0 }! B1 I5 s. Q; a7 z- U
enum {
0 E% L& y1 I: ^2 Y UPNP_OK,
9 Y d# ^+ Y! e# D" v( l UPNP_FAILED,
9 }8 e3 x) q# `2 }! N! } UPNP_TIMEOUT# b+ _: R! \$ L: }5 T
};
3 f# _* g1 H. h" z' m, U, j+ N7 L
[8 C: J' x% g+ S3 i5 R5 s
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;
, G2 |- D- M2 Y# P( W- Y virtual bool CheckAndRefresh() = 0;
: F! g+ K. i }4 s, L7 w4 _9 k virtual void StopAsyncFind() = 0;
) j$ F/ [# s7 ?! h virtual void DeletePorts() = 0;
/ T1 |& H, b$ N- G% ~) a# N7 E virtual bool IsReady() = 0;
; h/ {: Y: X" p9 s1 ~& Y virtual int GetImplementationID() = 0;/ ^$ l, X! h( ]; u _& E1 U
, Z( U$ v& K2 [0 H6 l
void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping
( V+ l! \7 ^, t6 Q* F5 ?
* [& A! v5 C1 i( r7 s2 E( ~
- ^3 a5 R3 R0 f3 w6 J' o void SetMessageOnResult(HWND hWindow, UINT nMessageID);
3 c0 \1 L7 a5 n2 y5 I% S7 ~ TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }2 l2 m6 f7 q9 D6 g9 o: B G
uint16 GetUsedTCPPort() { return m_nTCPPort; }4 A/ @0 U, i$ d% M. D' E: ]2 H
uint16 GetUsedUDPPort() { return m_nUDPPort; }
0 @' ]( n& C- }9 @* C
+ i# @9 j1 V) T
# K; j9 j. v: p6 [4 I( {0 b! Q// Implementation+ @# a6 q) m- L" N
protected:
& T9 ^1 {$ b3 o8 J& y% C# y volatile TRISTATE m_bUPnPPortsForwarded;
$ z( y& L' T* K( E9 | void SendResultMessage();3 o) N2 M; `# W& f5 `
uint16 m_nUDPPort;7 ^7 V& L* {7 ?! y) J
uint16 m_nTCPPort;
0 G7 K4 a" g: ^0 ^" I+ K uint16 m_nTCPWebPort;
( R1 |( i/ n6 B- w& l7 B, K2 L5 Q bool m_bCheckAndRefresh;: G- ^% |1 P6 j
6 Q) Z9 ^9 ^/ [5 w1 Y
! ~) s/ ~) G, L2 B
private:- ?5 U9 X4 f5 Q8 [
HWND m_hResultMessageWindow;% K( P+ s3 f) j$ h2 U! e- x
UINT m_nResultMessageID;
/ N; e0 i4 u, u/ {2 T# w' ?1 E: ?, w4 a
8 V; {; d* X3 w8 v5 p" `6 ~+ [};
8 l, v0 S/ E- j* }
% f& B$ N0 L' Y) j; N! s9 n9 y9 T4 M5 c5 W+ M! d+ n" u D' m- G4 T
// Dummy Implementation to be used when no other implementation is available4 e: V. C& ?# f& D5 p3 v
class CUPnPImplNone: public CUPnPImpl
. L2 J2 s' k* ?% w! ~{
2 E4 f: K- i/ P/ q+ xpublic:- h7 }) M1 ]& s' e( a% [' k' B/ y
virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }
; T) ~( c& R4 _! k, r0 P: I virtual bool CheckAndRefresh() { return false; }
4 `" A+ D& J6 F* w virtual void StopAsyncFind() { }' Q' u0 q8 C1 z! F5 C3 {
virtual void DeletePorts() { }
+ m# T& Z: ~5 n S virtual bool IsReady() { return false; }1 A F. e" Q5 w7 T9 J
virtual int GetImplementationID() { return UPNP_IMPL_NONE; }4 @6 Q' q k2 I9 B a. P
};
' W, D! b& @9 d* [! ~; J, f# h: T7 ~( Y+ X( A- C ^. n5 Q- j X
U2 s2 M- B: {/ T/////////////////////////////////////
9 w" Y5 x: E; n; u+ E* {. ^//下面是使用windows操作系统自带的UPNP功能的子类
8 {: [4 w: A v6 q \) ?9 Z3 @6 z4 c% ^
9 H3 }$ ?4 b/ f/ ]) I#pragma once0 T8 |! m* E% C, x% {0 d
#pragma warning( disable: 4355 )2 d3 W" F0 |" O& J
+ W. t. \! v" W+ L) M2 g! H3 D7 a- b) b( s4 ]* V% d2 ~
#include "UPnPImpl.h"" N/ Z% A" q) n# C9 _# ?! J; ]
#include <upnp.h>
# K! I C9 M4 M#include <iphlpapi.h>( o2 }, Q0 Z/ V: Q
#include <comdef.h>
6 [3 w6 m" P/ Y4 N; I#include <winsvc.h>
( L5 \2 ]. O$ O: s
: Q3 Y3 t( E& [/ W) b2 [# z7 {: v9 S8 P# E* B) y, \( p
#include <vector>
( ~4 _& T& v9 A5 e#include <exception>
$ X+ e) S9 b! _- b" w/ P#include <functional> y- b8 I% G, p+ V
, F d1 Q2 \+ H! }2 U/ V/ V6 W- i5 g
! l6 R e' j Q: S- r* w* w8 N8 @3 O- P& x
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;: d) K* o8 `' G' i8 O: @% l$ ~
typedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;* T6 a% p1 R' q J* m/ Z8 U: V! _
typedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer; ^" c" K8 G4 F) b
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;( n, c0 S9 N( r; N
typedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;3 y6 _; V* v7 Z
typedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;
* |6 e3 ~& p" Rtypedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;
1 }/ l* n( B5 {+ P; k/ L
0 }7 G- Q9 r @" W* e
. k" m- \/ ]; D; jtypedef DWORD (WINAPI* TGetBestInterface) (* ]* m) f D& D" G0 d# c- W% q8 C
IPAddr dwDestAddr,
- E% s. j" l m/ m6 W- n+ N! k PDWORD pdwBestIfIndex0 U: n5 w1 L6 W& o f5 U* m5 F
);
2 {4 L) p+ Z! U9 {( j. ~
% r3 _1 v2 f g3 ~) m# B! ?$ z: A8 s4 X8 C
typedef DWORD (WINAPI* TGetIpAddrTable) ($ U9 k. r! N# H% ]: c! W5 Y
PMIB_IPADDRTABLE pIpAddrTable,
) O5 d/ I% Z1 q, I6 j PULONG pdwSize,
/ g1 v/ Q7 b; Z! L3 m- m5 K3 c BOOL bOrder
3 g5 n5 T' Z8 b$ z9 P2 W);, [4 k9 {2 J a" K( U
4 R" i0 I% o; u; _- ~$ q. Y" j
9 V' r2 c: I) s
typedef DWORD (WINAPI* TGetIfEntry) ($ Z* {0 C5 w5 Q0 u6 n" h: M
PMIB_IFROW pIfRow/ D* f, W! r1 ]: E! z
);
) _" u0 Z' B, ~/ _2 |2 e2 d% {" y
8 m% _8 Q/ n; f- l, C4 U2 _! ~) R7 Z, e9 c4 V% o! ~& K
CString translateUPnPResult(HRESULT hr);
/ @* S) U9 {0 e5 aHRESULT UPnPMessage(HRESULT hr);3 C% D' k/ M1 P, q f
% W; p8 v: E% T+ A0 V
( c7 A! B5 L$ @3 uclass CUPnPImplWinServ: public CUPnPImpl
/ t4 r3 z- P) D" O{3 X2 @$ x* I. {, D/ V
friend class CDeviceFinderCallback;4 e' q h2 S# @5 T8 t/ D2 o3 n
friend class CServiceCallback;
, o, E( k! O9 m5 v// Construction
M9 [* B: L( a# K- ]- lpublic:, z: ?# E& i) q1 ]
virtual ~CUPnPImplWinServ();
; N' c; X* c( q CUPnPImplWinServ();
& H. Y* M; w, P4 I1 P/ ?1 ~; h' Z2 }, Y% ]8 k. x( T$ l: K
6 |1 D; ?' L+ d! h2 f
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }
+ j- }# v1 m/ q5 c virtual void StopAsyncFind();" Z. S, I0 v+ N. P W
virtual void DeletePorts();2 i/ B3 d* H* l9 j) [
virtual bool IsReady();
$ F( E& Q" `) `5 ]; m; a virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }0 u9 w1 N; I; t) B) ?" c2 s
5 y \" k( E8 `+ s% o+ l7 X3 a+ r' W* f! y+ O" a- O
// No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)5 Z: S+ X: ^5 P ]
// the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later7 y9 x& B. B( w/ v" D9 I$ o. Q. L
virtual bool CheckAndRefresh() { return false; };
) o) q# h0 ]9 e2 [& D
h$ [- l* S3 x- H7 D& o
! `( t& b9 ?1 C3 l6 Zprotected:
3 [1 @8 p; L# T& L void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry); [, `. j) j7 P
void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);
) }" I" @1 a4 m9 N$ H0 G5 L8 f void RemoveDevice(CComBSTR bsUDN);, e, g' i J4 N
bool OnSearchComplete();
* ^# G5 x9 Y% y. T$ {0 E* Q4 _ void Init();3 ^/ S# m7 w5 L% Y( G- M
3 V V$ f- x z# u3 R
$ N" u/ q# e3 ?0 U) C3 z inline bool IsAsyncFindRunning() 1 l6 Y9 ^, l* F& R
{
- X% f1 H2 \% J if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )
) D* b/ v6 v! s: n2 @7 B( p {7 q% y9 O. ?- O
m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );
W9 F! ^( ?7 |8 X* d" h m_bAsyncFindRunning = false; ~1 q2 ^/ F W
}/ y6 ~! _, R' _& o
MSG msg;/ l9 {) O+ P O- ?$ o- }
while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )8 _ m- q+ t" n7 O9 ?
{) V1 R8 g2 J+ o
TranslateMessage( &msg );' z+ f4 z1 p ]9 X& \
DispatchMessage( &msg );
6 d9 M% y4 S2 }- _ }% T, {- t1 G H; Y1 y$ [$ k+ M
return m_bAsyncFindRunning;3 j0 }$ a1 s9 `: ~
}, P* A( I! t& ]6 n- |7 n6 X9 l P
: K& C6 H$ t* r U- {5 s0 a5 L+ x: H* y7 F+ ^" ?1 e
TRISTATE m_bUPnPDeviceConnected;; r9 Y# `6 Y e+ Y1 x, W
) X" L3 Q( `, D% M# g% G& J- B% |
3 [! v) i/ z/ \
// Implementation
: h4 q# U# O, y# l j // API functions' @3 c6 E5 N0 m7 n" H3 G6 S
SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);
0 a+ u; T" z/ x0 v p" v) ? SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);
# n) b# D: X: |+ t BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);
% c* u& l$ b! F5 t BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);
: _: J6 n1 b+ ~. f1 j9 y BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);
- j" i6 j+ }+ m# t7 Q0 @$ v BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);5 [: x* f1 Q. o- |
1 |4 b- J+ F; B4 z3 |0 |! P3 N9 m7 e5 n. T% ?
TGetBestInterface m_pfGetBestInterface;0 g% p9 y& N8 D3 H1 z& V' T% P
TGetIpAddrTable m_pfGetIpAddrTable;
, a* k' O4 P" a$ M9 ?& |/ O( H TGetIfEntry m_pfGetIfEntry;9 n$ U# N# B: _7 F4 j" M9 \. Z F/ q2 d% q
! `' I3 Y* k* z) v+ E. C/ S4 w* F" @1 j8 w2 }; c2 [" K7 `
static FinderPointer CreateFinderInstance();& N) l0 M: J7 K7 T4 Y0 f
struct FindDevice : std::unary_function< DevicePointer, bool >
8 r6 h; A& c: M0 q {
1 z( g7 i, O5 ~6 N; A( K* n- `: d FindDevice(const CComBSTR& udn) : m_udn( udn ) {}
" T/ v. B1 S" y+ J result_type operator()(argument_type device) const
3 l1 G! w, D) a' G6 T, z" S2 m {2 F& j% U! P4 ]& S% P3 M. Z" P
CComBSTR deviceName;8 E6 K- k4 F! t: C! [( t
HRESULT hr = device->get_UniqueDeviceName( &deviceName );6 [6 y8 U7 F6 W
2 C# }3 V' s+ X& @9 q% J1 u3 ] ]; S' B! N4 k( @6 k" c) B
if ( FAILED( hr ) )8 ?9 T3 R9 K- W o- w% x1 W4 W+ z
return UPnPMessage( hr ), false; K0 S. ]5 O( W1 y/ D
o# e. ~2 r/ F
3 g; Z( Z8 ^' b* X1 z7 d8 |+ I return wcscmp( deviceName.m_str, m_udn ) == 0;
' u# X3 j1 n k4 A }8 K4 s' c0 b1 {* f
CComBSTR m_udn;' G# E1 A% U' }2 Z6 w% C8 @
};; q, Y0 a B2 O4 ^1 {2 M
+ V( }! f8 d$ |. s
void ProcessAsyncFind(CComBSTR bsSearchType);& {* n3 n0 W1 Q% }2 C. I7 J
HRESULT GetDeviceServices(DevicePointer pDevice);4 u7 Q& k6 ^( K+ n. G; b C! [
void StartPortMapping();; L6 a, n$ G! {( w& }
HRESULT MapPort(const ServicePointer& service);
1 A5 T9 }) M7 K void DeleteExistingPortMappings(ServicePointer pService);
4 }# X8 e1 t( S7 D void CreatePortMappings(ServicePointer pService);
+ O4 R) N/ J0 X+ O HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);# O: t' C: M9 U3 T( R
HRESULT InvokeAction(ServicePointer pService, CComBSTR action,
2 S' G2 h% {: V2 ` LPCTSTR pszInArgString, CString& strResult);
1 q: Z o4 S1 o. l' l# c; Q0 G void StopUPnPService();
, {& u+ c* {, y, ~- Q2 V8 E
% ]- L, `+ Z* c; h+ @; l( {: c0 i6 Z
// Utility functions
. |% @) p/ q. P% Q5 U HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);+ P$ R8 A/ T( `' }7 S6 b! [# h
INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);
* k- z6 ]: V! L2 Y9 [7 V0 s: T8 C INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);! X0 O) _5 C3 O+ W! \3 b* n8 V
void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);
/ S- N+ l! Z# l* c9 P HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);
+ B: l$ L/ F* Z HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);# f8 w( p9 W q
CString GetLocalRoutableIP(ServicePointer pService);
# C0 t) `; @1 ]0 e7 M" z B( n) E d3 g$ h J4 R
' l0 j& W, u3 I' Z% u& Z, ]* A// Private members
6 K, k& H& c! | y% sprivate:( b# V: `& r, w k8 T' V( L) r
DWORD m_tLastEvent; // When the last event was received?1 C( W4 k9 o3 t- @
std::vector< DevicePointer > m_pDevices;) e: a$ I0 |" y' a, E( `+ E
std::vector< ServicePointer > m_pServices;
+ U' j, u& n5 X9 Z, v FinderPointer m_pDeviceFinder;
0 \, N8 n% ^ ?" D2 J DeviceFinderCallback m_pDeviceFinderCallback;7 l1 Z: k) j+ v6 y6 ^
ServiceCallback m_pServiceCallback;
; g8 F+ |2 \, i9 p* Y
6 Y. t0 O, m; i) _, t* _# m. C- C/ F8 k/ d# E/ u) \& G. c
LONG m_nAsyncFindHandle;. u9 D7 M/ w3 U0 b- ^) `9 C' c
bool m_bCOM;
. b% n9 ~; W0 s' ~7 R5 d* v6 I bool m_bPortIsFree;
* |0 @2 h4 \1 X# | CString m_sLocalIP;, T5 S+ u7 m4 ~% Q* b: ~# h6 V+ k
CString m_sExternalIP;6 [5 U" C: D% A- x2 B
bool m_bADSL; // Is the device ADSL?
" }( g- o! t) y+ Q9 C$ }: A& R- P5 m bool m_ADSLFailed; // Did port mapping failed for the ADSL device?+ }8 f. h5 Y& `2 y" ~$ x
bool m_bInited;) R2 S& R$ L$ D$ \, j+ b0 N
bool m_bAsyncFindRunning;& H2 y9 H3 _1 c! T/ g) W! j
HMODULE m_hADVAPI32_DLL;* V9 T. O; t6 k. g( w/ p; R
HMODULE m_hIPHLPAPI_DLL;- s# v& U* ~, c/ q, g- E( S
bool m_bSecondTry;
/ W# ` F7 S6 [* c( r. H& c bool m_bServiceStartedByEmule;& R; r9 C; h3 x+ x) g$ a- d
bool m_bDisableWANIPSetup;* ^; A" [! c7 w7 e" G
bool m_bDisableWANPPPSetup;4 x' ?3 _0 [# l% ~, L2 M
& v7 T2 \1 y" C# L! f4 N% |- A: k7 f2 G( j( W* e( f5 e
};
; P4 X0 R* m+ Q6 H- W
0 n q5 |- ^. |; i& O& I$ r$ E
// DeviceFinder Callback/ Z0 d' B- o1 | f1 F
class CDeviceFinderCallback; a8 x C) f6 k
: public IUPnPDeviceFinderCallback
/ B% o- e2 X; j4 R8 l/ s{
. H1 R0 W8 P3 i6 } Bpublic:
; r* o7 Z& {0 c8 U1 e( k CDeviceFinderCallback(CUPnPImplWinServ& instance) ]- z' b& g+ X
: m_instance( instance )
; V5 L. k3 M% x$ P# L' V! L { m_lRefCount = 0; }
( {6 ]+ f! ]: \& c8 ^
2 a4 P' [% r0 x; h" n3 w4 v( Y; C c+ n3 w3 F: m! _7 P( a8 ^6 w
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);1 S) O+ B+ m( h. Z D4 }
STDMETHODIMP_(ULONG) AddRef();% _* N9 N& F r" n& m1 V+ `
STDMETHODIMP_(ULONG) Release();
8 r5 a1 D H# N1 b1 {- y
' ?5 Z. s+ f6 m/ o' f9 X0 o' q
9 L3 p+ K; n' H( [$ h/ ^// implementation
3 H' C- N" u3 |1 }private:
" F* G. j8 R+ g& z% B ~ E: V HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);
) U$ ~+ T7 o7 ? HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);
& I, v. \. v% R- ^1 h HRESULT __stdcall SearchComplete(LONG nFindData);
3 a. k% i( y, R( p, u$ U1 `0 T0 S; V6 ~3 ^! i( h
+ c% K; R! d+ k& y1 z
private:
, g' R$ i; q) N! \$ H CUPnPImplWinServ& m_instance;6 }' m! S# `( H/ n
LONG m_lRefCount;
$ c! P' R* [4 n U( v4 ~' j2 y3 C};' p, Q5 K& R; v; \, K9 ?
, _6 @3 N" o. T+ T2 k# J" Z- |; h0 u! ?; L/ k. ~
// Service Callback 7 e- c, M4 f; x) P$ R X% E
class CServiceCallback- _3 ~5 c8 P( W) p0 @) }% ]
: public IUPnPServiceCallback
! o5 i" A) r+ `! Z% g$ @{
* z9 p# _) c8 j" _6 e5 i. `public:
4 I* R! P! w0 v4 m CServiceCallback(CUPnPImplWinServ& instance)' \. a7 C5 ]- c V
: m_instance( instance )
" ?% ~" r2 H& @" s9 Z; u. x { m_lRefCount = 0; }3 N' ?6 s8 F6 a1 X. g6 @* q7 y
. D# s X6 @6 w
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
. ~5 _! ?+ U6 w STDMETHODIMP_(ULONG) AddRef();
# ]5 @% Y/ M, t7 a# Q STDMETHODIMP_(ULONG) Release();- F, i- ^* F7 _1 T
: X. U- J8 ?( v' Z* a0 x# X
. E3 n3 L% i" L1 P) E/ B9 C/ |// implementation
5 s6 R) g5 [) [" v+ aprivate:* Y0 k7 N; ^( p3 H3 D
HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);
+ q1 z* M3 J2 z, V. ?% v; D8 Y' [ HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);' s$ b. C" G. M# \
+ Q" c, w% j/ H2 x+ N" P; c: X5 G6 C4 ]* i/ [" @" E' s+ s
private:
! I& @3 a- Z& {3 _! u! K CUPnPImplWinServ& m_instance;: J( z& ^- ?& ?5 T
LONG m_lRefCount;
) p M# m) m* K! F6 I6 S};9 B* n- b* u3 e3 R; C$ s1 F
2 u7 z( } y+ B: u
& O3 v" u' Y5 q' `$ x& H/ g
/////////////////////////////////////////////////
5 d3 e; F3 B; J; ^1 [
+ h& U1 j6 a6 j6 m5 d8 }' E, q: z0 X8 k: K5 H$ h3 N
使用时只需要使用抽象类的接口。) G+ K5 c$ p! l. Z6 ]
CUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID." p0 S3 y8 i F
CUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.
7 F8 v3 n# g* f( GCUPnPImpl::StopAsyncFind停止设备查找.
. N$ {2 s& C9 T/ @# m& Q' oCUPnPImpl::DeletePorts删除端口映射. |
|