|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule,9 n) _3 ^9 G7 k3 { D: w
& V1 c# o' `/ O$ @
+ x$ X D O1 ^0 {# q+ B/ ?///////////////////////////////////////////. j7 }" ^, H" g, M8 W# d
//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.: @; x& A& E0 D
( P5 L! F' b4 j+ g B0 v" R- q j9 s. H& H! ] Q
#pragma once
* _( T! k8 p8 [0 o( x( h2 Z% v8 G#include <exception>
1 L& V/ Y5 c& o) w( e* J- z
7 d! ?7 z/ r, M5 {" @
* e F! C5 M. P+ s; D enum TRISTATE{: u9 _, w# Y) b
TRIS_FALSE,# l4 O8 B* s& ]0 V I
TRIS_UNKNOWN,
$ I" X3 ]7 l7 F' e, n TRIS_TRUE$ Z' b: G8 F+ x6 E
};9 B* W% q; {( A' F& C* T+ U
# E! C1 S5 u, s _( T- D0 E
" z6 ~: z+ h$ k* eenum UPNP_IMPLEMENTATION{. f' ?2 N1 y8 o A" s3 E7 @3 ~
UPNP_IMPL_WINDOWSERVICE = 0,% g) |! R0 X$ |: k: f0 f6 A
UPNP_IMPL_MINIUPNPLIB,
- r& c% `9 U/ N9 ? UPNP_IMPL_NONE /*last*/
) c: M+ T6 L/ n( Q+ ]) H};2 Z# K& o9 U% d. j x) a Z7 \/ k
$ f+ C S: C: f2 M2 }- B7 K' O$ Q
. h! W+ h5 v) R. E4 c
( w0 z) @( ]9 @" ~4 {
# b) ^' x0 g' e4 O1 U o J) kclass CUPnPImpl+ l7 l" t- b0 |/ H
{, U u5 `# i2 y
public:$ K/ w! a7 Q f9 \$ c" p; q
CUPnPImpl();/ C& ~0 u$ ]/ k
virtual ~CUPnPImpl();( w% W( p9 E7 O% E
struct UPnPError : std::exception {};; J$ ?) A" x% W$ H
enum {3 I# \ s5 f4 a' D" ?* o0 E, D6 ?8 _
UPNP_OK,, h5 A+ h- }. Q
UPNP_FAILED,! ~" S) i8 S0 P1 ?, o; h
UPNP_TIMEOUT
N5 U f. G" G& \, w. l };3 T8 `! J4 z# d" {, \3 f* O
/ O6 j% f0 v) f" d! p% b& O5 k7 _- W& m9 a. T7 G3 u n
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;% P$ x: {$ h( z+ j8 n' \! e$ o
virtual bool CheckAndRefresh() = 0;
% t$ F! t; y! o$ M6 b6 k: l. Y& ~ virtual void StopAsyncFind() = 0;$ q2 q5 _- A! T, Z/ ~- G
virtual void DeletePorts() = 0;
* m% |0 p+ T! C; w) G. { virtual bool IsReady() = 0;
/ p3 O6 z: d- M9 ^' n' I x virtual int GetImplementationID() = 0;
3 p7 V' ~9 h O% N6 i( }
" l3 W0 m8 z& D( B8 v void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping5 G( ]& n2 i% @9 K: h$ G+ m3 M
6 r: a# Y7 w0 R# H# b7 \) S. |3 y" s* C6 N" N
void SetMessageOnResult(HWND hWindow, UINT nMessageID);7 e# w7 o5 t1 B# ^3 H' ]1 g
TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }
& y1 s6 p6 A [9 z+ }$ H uint16 GetUsedTCPPort() { return m_nTCPPort; }9 ?$ p3 n/ z/ U4 J2 c8 z
uint16 GetUsedUDPPort() { return m_nUDPPort; }
! K5 O( I( q6 D6 w: h6 r2 R6 H$ T2 g+ Q
5 I+ s9 s; v9 a+ q! D6 s) Z% d
// Implementation
- I& _( o, r; F/ U6 eprotected:
/ w2 N, \/ G6 f) y, W# {9 f volatile TRISTATE m_bUPnPPortsForwarded;: f/ M# n7 Q+ C# D* e& V
void SendResultMessage();
/ O* W2 }0 N G7 o uint16 m_nUDPPort; T* y, Q2 T$ S- R3 I, J. t
uint16 m_nTCPPort;
$ k8 }, D8 Z0 q, S uint16 m_nTCPWebPort;
7 [" X: @3 u6 B$ C: Y( y bool m_bCheckAndRefresh;
+ o! [& e8 y0 H2 s. P: y- K# M1 j C: U3 x4 o
( b2 }0 Q' R# N' Oprivate:+ f0 E- M/ g7 p8 U; e" ?
HWND m_hResultMessageWindow;
C' v. i6 F/ F& i7 Y UINT m_nResultMessageID;4 i6 T) `. O8 Z8 A& P
! x8 X1 G7 z% |" @: a
1 A/ l& F, X. W" c4 _- j( Y};
2 V+ o3 n# | Y0 E4 m4 Z
# T& _' }. m8 o
" t M1 J2 a& ~, S// Dummy Implementation to be used when no other implementation is available
( p2 i6 M4 d$ g: o! [0 ` Tclass CUPnPImplNone: public CUPnPImpl
. k! J) f& s/ u, [1 t{
6 e3 [% i& N" T( D0 ppublic:
8 o# t! }) l5 u' ~: x virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }1 Q1 k/ C$ r9 Z4 U% P; x
virtual bool CheckAndRefresh() { return false; }8 o, o" b+ w) A2 D
virtual void StopAsyncFind() { }# h& y5 u; r' M* ?+ p3 p
virtual void DeletePorts() { }
2 `6 I# y8 C( i* g/ @1 H6 p0 b0 o virtual bool IsReady() { return false; }
9 U& V3 y& ?6 `" _ virtual int GetImplementationID() { return UPNP_IMPL_NONE; }
; t/ Y, v! V7 u# ]};
1 `" q1 `# a `" f. F
( n9 L* `8 N3 a2 F+ L1 E
. A- M6 G* a4 e4 k) u( \/////////////////////////////////////
6 ^' i- d/ o6 @$ l//下面是使用windows操作系统自带的UPNP功能的子类0 @5 E. A4 n3 ]& j
$ j, d4 W9 F1 ^$ o4 m; D
2 W5 Z2 Y3 F. ?* D$ o6 x#pragma once
- p3 t: E9 x- Q$ i! c#pragma warning( disable: 4355 )
; @4 I1 B, q7 O: `7 ^8 F/ ?
" E! {( J8 E$ h, C) c6 J
$ a# v% c9 T B# ~+ Y1 b#include "UPnPImpl.h"
8 b) R& i* G) T# j4 B#include <upnp.h>
( x' k5 n' p3 h2 l8 X5 \% {0 Y#include <iphlpapi.h>- W- W8 V9 S a2 A2 f9 Q
#include <comdef.h>" h0 u% L1 i4 {; d& S2 _
#include <winsvc.h>
: }, ~/ Y% Z. b( q4 ?) y' E0 s. B& _, o6 p) X) B
# M; _" R( m" Y6 t/ H
#include <vector>/ |. T9 j. H9 w. l$ E" F* ~
#include <exception># t- D8 c% r- L+ z+ r6 M9 U. c
#include <functional>
1 J7 Q$ J4 |* f8 R
3 d5 T7 @, Q$ G8 K S
2 b$ F Z+ b8 @4 G
- }3 @- C# l# W! K3 W7 T2 d$ u, o2 R* X. F
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;
$ m# {1 i+ I% @% J8 btypedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;
M: @. I( _/ J% J1 i" c: dtypedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;- g6 T2 f1 B7 s. B9 F
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;
! n, U6 O8 W* [- ^5 y$ F; N" Ptypedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;) F& P6 w5 F7 _) {4 B) E8 B
typedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;
% {1 o4 C% Q: \' p' W- v: J! K2 C' |0 ~typedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;% d; O) l' V. @$ |8 K' S' W
9 t! g% w# g. k
5 Q% w9 h$ G; Q$ l* ntypedef DWORD (WINAPI* TGetBestInterface) (
6 u" p5 h9 F7 S6 q j6 k8 t9 T IPAddr dwDestAddr,' P1 d3 U% B" l5 W) U7 R# d4 F) A
PDWORD pdwBestIfIndex
' r3 n0 {8 X' }% r7 |);! a, E% T4 x. ^
& e1 @3 H. c5 C
1 }( j+ k5 l/ q8 a( r) X, W$ U9 gtypedef DWORD (WINAPI* TGetIpAddrTable) ( o' J9 Z5 Y8 H
PMIB_IPADDRTABLE pIpAddrTable,7 v( u2 \* S3 h- O6 @3 [
PULONG pdwSize,
; T* ~6 ]/ t$ p3 u- s BOOL bOrder
0 O3 g1 h& e. p" I& {' o* m- m9 k);
- b" A. L2 E7 E* [
; J- l8 h& e, t) n: S* c/ [) N8 O4 @) {& Y
typedef DWORD (WINAPI* TGetIfEntry) (
+ K3 B/ j m) T' `0 p. C PMIB_IFROW pIfRow* u6 T" R1 M# J) ]8 e
);
6 \2 H3 a2 s1 }! {; v6 D' v' ]
' T% P6 Y" M( C5 ]% ^, N3 E3 ^; ^- n( ]0 P
CString translateUPnPResult(HRESULT hr);
6 R% H# p+ Q: y/ _# ^; kHRESULT UPnPMessage(HRESULT hr);. B8 O* ?$ ]/ m3 a. @" T2 \
8 A5 k& o5 {+ c) S- s1 Y1 ~
9 V& p \1 o& ]class CUPnPImplWinServ: public CUPnPImpl3 x, z8 b( O+ f' _3 c2 i
{7 z+ M( ?* K5 [' ~( f0 t( t9 {
friend class CDeviceFinderCallback;1 @+ u9 o& s- t8 _
friend class CServiceCallback;8 y, a$ b5 S0 q; B& L
// Construction
2 F8 }: l. s9 f% P9 cpublic:
6 n b9 C* l; M( w virtual ~CUPnPImplWinServ();) W" X( ?( l9 T9 ^, X1 K
CUPnPImplWinServ();# ?2 Y5 |- l+ s( v. l
6 c! s" Z" r/ P) ^
6 M) W+ }) N, Z
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }$ L s, R6 V8 V" Z; D
virtual void StopAsyncFind();
9 @' E" J1 V2 A; s6 U( D! J virtual void DeletePorts();- ]0 t. }* v+ o( }9 ^. P7 L' @
virtual bool IsReady();% u- l6 J }& c9 d
virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }" Q, i* F2 g; p9 j5 j
" C' I D5 F( C0 d/ }
3 P6 l* @; M% V6 S // No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)) s% e9 a m4 I' Z3 z+ h9 V
// the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later; {$ [) x, L6 f
virtual bool CheckAndRefresh() { return false; };
6 W9 N, _ f' j3 C
8 f+ y! b, Q% S
. G5 W" V7 I& y- lprotected:/ p# @: }7 [6 ~* ~4 h, p
void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);0 I8 _, U& _) y J
void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);
! D3 M( x* Q& U& g; j3 s# E void RemoveDevice(CComBSTR bsUDN);6 ~: X+ g" R4 L9 D& d
bool OnSearchComplete();. L+ j" V. V# L: ]6 |# S/ j
void Init();$ ]! X. }+ D: R( n6 d7 E4 q
) B( ~4 l2 D* {) A
' D: R1 [( t% v. b0 V3 G/ G inline bool IsAsyncFindRunning() [$ R- z ]8 a/ J) ^& I( y
{9 i$ ~( p4 w% J
if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )& }! f+ }% X/ v: i) [
{2 V3 o$ d7 c# I/ F1 S
m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );
5 H4 o2 N- M' Q( A m_bAsyncFindRunning = false; _! m1 v( q* Q6 |( i
}
M& j0 n0 c, S) p MSG msg;7 c f! ~1 ~! K; [% Q4 ~
while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ); @2 D b* S% i, x$ h
{8 W9 B1 ^: S, S9 F) \+ t3 v4 ]
TranslateMessage( &msg );
8 u) _; m! }2 [% `1 h' c" x) N4 ^8 X DispatchMessage( &msg );3 w$ c) ~* O( R/ h. ?
}
+ D! A! A V3 b; I3 T; ` return m_bAsyncFindRunning;; _, W( q( z' C2 k# v
}$ s9 n" c: S$ q6 B
+ y$ m7 N' R v0 U: x* a3 P& p% H( z+ R6 J
TRISTATE m_bUPnPDeviceConnected;2 c5 ?8 D; Q) S( F" }
% K; `/ x9 O3 I
4 V4 R- ?1 i( C* a- R// Implementation
% E& ~3 m/ a+ j3 V // API functions
2 D1 q, `- d8 N, c% E$ g" S SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);
$ Q# \( y0 L7 N' c8 ^! C1 g' P/ I# O SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);; ]& P" m# u, d: R; n
BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);
1 F" r: A7 B: W5 n2 B4 Y1 ?2 R BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE); ~, P" w5 K G6 s1 u' H1 g$ w& j- d
BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);
$ ^5 C- W1 h% a; F- n5 H5 ` BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);2 P+ I6 [0 V7 d3 g9 c# t: d
$ G$ [1 J' k: E
6 `1 i$ n1 J9 u3 X TGetBestInterface m_pfGetBestInterface;
+ T- h0 T5 R* c TGetIpAddrTable m_pfGetIpAddrTable;
% g8 `( M6 K( q2 \. | TGetIfEntry m_pfGetIfEntry;/ q: u( N/ O3 p4 H+ a
4 K" [- \# \; C# G0 ~& K
. H/ w! \% e/ n2 C static FinderPointer CreateFinderInstance();( L% J: X6 j; t# m3 U3 u1 {; j
struct FindDevice : std::unary_function< DevicePointer, bool >1 `4 F% ]" T( U% o- q L
{8 y6 ~* q) j& h& F% N5 d
FindDevice(const CComBSTR& udn) : m_udn( udn ) {}( _9 T7 l( F o( P% z
result_type operator()(argument_type device) const9 ~% B% p0 J8 G# ?7 j5 n. f
{2 r& P l# q# L' W7 |
CComBSTR deviceName;
. @; }' v6 }" } HRESULT hr = device->get_UniqueDeviceName( &deviceName );$ b5 t5 A5 Q3 M
' ~( r$ x4 F$ y& C) d* Q
, x9 H5 O: h# A, H) P if ( FAILED( hr ) )
* P6 [4 A9 L8 X# C return UPnPMessage( hr ), false;; m& v( H0 a5 G2 ?$ @# n& D
0 R2 K P, O& x- V# ?5 z
! i' d7 F/ L6 _( y# O$ B: {6 C
return wcscmp( deviceName.m_str, m_udn ) == 0;) b4 A( X2 ^# `, {
}
6 V @; A2 J1 z: V+ X8 I6 Q CComBSTR m_udn;
- x4 V) {4 m p% a; L& h: ` };
( ]9 Y- r& @* ~2 F7 `" t( J0 v 2 Z: M5 ?# e O$ K9 Z
void ProcessAsyncFind(CComBSTR bsSearchType);; |# A) F& z- u" U( t6 n
HRESULT GetDeviceServices(DevicePointer pDevice);# i! I, A; Q. F) T" p& p3 O
void StartPortMapping();
, r7 i* v% G* F7 _- s/ | HRESULT MapPort(const ServicePointer& service);
9 ? Z5 p5 t0 D0 \$ b7 E void DeleteExistingPortMappings(ServicePointer pService);7 ?9 S* j# r! `0 R
void CreatePortMappings(ServicePointer pService);5 w9 e4 ~- Q( [; F7 r
HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);
q1 q; E8 R0 U5 r1 z& l- R/ | p0 w HRESULT InvokeAction(ServicePointer pService, CComBSTR action, o; A5 L* C9 l2 ], t# S+ x/ v
LPCTSTR pszInArgString, CString& strResult);4 F6 ^* V( A8 p
void StopUPnPService();
0 X) V4 d' F7 T6 x, k f# h5 P* p6 o- \) _" c5 `
0 K8 A& t Z7 z/ R // Utility functions
6 {8 P; s/ ]5 F1 [ HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);5 @ G5 }% \9 N* n7 a& W+ y
INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);
O& c: Y( F- s" c; @2 Q INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);; Z1 ?/ r5 {" y# ~/ y: } G
void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);
; N7 ? R2 L/ J. z HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);8 E; K `+ @, R8 @
HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);
& | @ m5 f2 C1 f CString GetLocalRoutableIP(ServicePointer pService);6 ? q# V& E$ P, j9 s5 |6 q
6 u6 h3 [% e' a2 g
; r0 I( H4 A3 {// Private members
3 `3 X4 E- s0 `- {7 N% B; _private:
! D4 k0 G( r: D DWORD m_tLastEvent; // When the last event was received?
) |3 Y* g1 ]) P. a std::vector< DevicePointer > m_pDevices;
4 ^% T1 w. p1 z4 e std::vector< ServicePointer > m_pServices;: V: L: p" m. j2 C& c0 i
FinderPointer m_pDeviceFinder; k3 c7 X. c9 p. g
DeviceFinderCallback m_pDeviceFinderCallback;
1 E$ T4 |9 J6 M+ i6 O ServiceCallback m_pServiceCallback;( F+ c! h# |$ Y( e
! t$ y1 e# f* n o$ q
" n% }; j' T1 [ LONG m_nAsyncFindHandle;: G% M: D" I3 V8 Z
bool m_bCOM;
N- q+ }" F' b- a4 c. b4 p4 S bool m_bPortIsFree;+ u0 v& R9 a" {2 @) x
CString m_sLocalIP;
1 {, c% ]; Z4 ^- t CString m_sExternalIP;
) A6 t- [3 |% D2 ]! D bool m_bADSL; // Is the device ADSL?
+ {0 \, ^: {5 y9 |7 U bool m_ADSLFailed; // Did port mapping failed for the ADSL device?
W2 l0 m# _9 Z9 @* \ bool m_bInited;' f6 C B7 ~0 P
bool m_bAsyncFindRunning;
, }, g- t0 @5 J' Y" D9 ` HMODULE m_hADVAPI32_DLL;$ ?# \3 O$ u4 ^% u/ E
HMODULE m_hIPHLPAPI_DLL;3 ^1 f2 n/ |/ C
bool m_bSecondTry;7 }4 }5 z2 ]. u
bool m_bServiceStartedByEmule;
7 f% r2 V- V; x. t3 u4 h: S/ t% b bool m_bDisableWANIPSetup;. U4 r, S% Z) K0 R+ K- q3 Y
bool m_bDisableWANPPPSetup;
! @# H+ \" k- c: N0 a
; W8 c1 K7 u1 S- w, Z% p9 P
) K2 W7 F" U0 Z5 a- V};
% ~% A9 @) z2 L) ~& k
; Z, \! X& F! Z$ T9 W! d4 B3 T' y' O# H( i/ W, Q% l' }) u" d
// DeviceFinder Callback( r9 L2 n% R/ o+ u2 L4 D
class CDeviceFinderCallback s; ~' H. z0 I: h* f( h) y
: public IUPnPDeviceFinderCallback
0 H5 ?* s5 C' w) c u{
3 d; L, M" Z# Npublic:
8 T" J! d3 s' q' N5 ^0 N) D! H CDeviceFinderCallback(CUPnPImplWinServ& instance)
0 x/ E6 T! W8 n. I& a3 F, m : m_instance( instance )8 l/ n( Z, q" V8 u: p0 F+ S
{ m_lRefCount = 0; }
0 F6 V, b3 }- h$ H. w* X, ?/ D: t2 @* l3 O( H; k
0 h6 S7 R+ `2 m, L
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);" \+ F0 f$ r. Q S0 S+ h/ M
STDMETHODIMP_(ULONG) AddRef();
4 w6 Y) q& Q$ z- g: o+ \: ` STDMETHODIMP_(ULONG) Release();, R! g5 |9 W6 L; q& U. W
% r) U$ u& B& j" e2 S. L0 s0 t+ N! i9 ]# n& W
// implementation
7 T: M/ ^1 {9 uprivate:
# I7 q* O& n5 j; Q2 K HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);
. ^4 H- E1 H! D' x HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);
' q8 v' E& }# k6 u' r( x HRESULT __stdcall SearchComplete(LONG nFindData);
: s. \ D+ ^4 B- _: _# j; A/ |1 ? L6 ]4 F8 X
' c" V! {- e" R/ }; M+ ]* {private:
1 A- W, p( q+ k( J, X CUPnPImplWinServ& m_instance;; @& y& Y$ n# B/ j. m- C1 U/ t
LONG m_lRefCount;2 j( S, g( B2 C! Z) W2 M2 X
};
' @8 V& A; Y8 `% @* T2 c3 t5 C! |8 d4 ?' e+ n1 O3 @3 X) n' O: L0 j
5 V; P# }+ K/ b, R; m' a. ?3 P
// Service Callback ( c8 E8 U0 {0 A: ~3 [+ w
class CServiceCallback8 b6 @4 j% C! z e
: public IUPnPServiceCallback) q) l9 y% B+ m+ g( n8 Y
{
1 T8 W7 H& a @/ a4 x7 N. tpublic:
; z( \" X5 E/ j' }: B& q5 M5 m0 B4 \; t CServiceCallback(CUPnPImplWinServ& instance)- w9 b' T5 G1 c0 r
: m_instance( instance )
o' @4 `5 X+ ~. G5 u { m_lRefCount = 0; }5 k# r0 L/ O' J8 d3 _" x
' k( o l) A2 s& F$ S3 U! \ STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);" n% _: b5 q9 w
STDMETHODIMP_(ULONG) AddRef();3 P" S; g- s- p# w- ^& n0 M5 {
STDMETHODIMP_(ULONG) Release();
2 u/ `1 @) F1 a; m; m' N7 G" F$ A) D
, V6 E* X- m! v, [% _
// implementation
# j3 c9 X( c$ }( ~private:
8 e% I5 b0 D+ O HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);
& f* B; x) h+ x1 H2 V# S9 f HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);( f0 R% |/ f4 r2 Q! m3 m% p1 Z5 o
9 N3 O% S# J6 \
6 ?, t# a' ^. I: l! D! q
private:
0 ^, }# U D o; E. l& { A CUPnPImplWinServ& m_instance;6 o- m {/ I# {+ o$ R" p6 p$ y; p
LONG m_lRefCount;
, W# M) z; A9 q9 ~# B};
$ l6 a4 Y, w j) k; f, H0 y' w8 {" p. m3 L% L1 Y- N+ A
7 u9 ^7 m+ D4 [. x' `; f& ~6 [( \1 I% H! Y/////////////////////////////////////////////////" { S3 L$ g1 C( m4 C2 f. S
( T2 ?0 G$ H- Q# Y6 B2 g; X- J3 r1 q4 s5 ^6 q( d, `
使用时只需要使用抽象类的接口。
( `" c2 D7 f5 S9 r) d0 W9 PCUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.
6 }# V* ]& w2 ^) A" G0 R G& x7 O0 aCUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.4 Q6 C$ \+ Z1 s. b
CUPnPImpl::StopAsyncFind停止设备查找.
- I6 |1 K# v5 f) Q# M" jCUPnPImpl::DeletePorts删除端口映射. |
|