|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule,& ?( Y8 @3 a3 Z$ u
# N0 j- z" |. `4 @2 ^2 M9 O+ s
///////////////////////////////////////////2 B( c Y' o( _+ T4 z
//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.& O1 Z2 [/ f% C" [# C: @
8 X* ^& v+ E! K6 {6 j8 p
X. L) T3 w/ S! t#pragma once
1 _& L A! L R2 `! R9 Z* y& P- T#include <exception>
, R C% h1 V& W& e2 L
' |6 @1 }' A9 @3 Q
4 S% ^2 Y7 Y% S& t4 h( C enum TRISTATE{' d9 k* C' P3 J
TRIS_FALSE,
5 q/ e% c( V9 r! a8 w1 X TRIS_UNKNOWN,
, e8 @0 [$ c2 ?9 U8 L TRIS_TRUE
4 H& q) Z' W T+ o, O4 `};
) Q8 a5 p) D0 \" F5 }) y# m0 h# I+ i! l* A; b- s
- I5 p1 T) f7 s2 H! m. ]
enum UPNP_IMPLEMENTATION{
- [) n0 \9 u6 L+ W3 w9 u UPNP_IMPL_WINDOWSERVICE = 0,
. M0 a6 e" l2 r( D) k UPNP_IMPL_MINIUPNPLIB,/ [5 P r3 M: P; Z# x
UPNP_IMPL_NONE /*last*/
! l( q3 y" S3 m+ ~" K};
- l! q# l( M( z3 E! r! t4 C6 \6 T/ j$ p* o& w; |8 J3 [+ N& e
0 H9 f0 K: H. h: Z$ T
9 i" _" }# G" y; S2 R; ~6 Z0 `9 R/ }$ P3 n( i: h2 ~! |1 ]0 t
class CUPnPImpl
8 G5 L9 |, p; m8 X, J{
2 |2 M$ t8 m' ]1 L5 Tpublic:
% f! D7 F' a/ A) @. J CUPnPImpl();
3 J0 W; H* r* I; b+ }: V; q: E- r virtual ~CUPnPImpl();% C' W! b4 x' M* D- o) L T4 E3 ]
struct UPnPError : std::exception {};
" `- n% ?% G7 t) F enum {
+ ?' D: z6 y, w8 g1 E9 Q4 y UPNP_OK,7 r; x0 u& v- x5 c
UPNP_FAILED,
/ z, A+ P/ j- G4 u7 P UPNP_TIMEOUT
p! j( t) m# O1 F/ M- K" w };
; q8 Y8 \4 K# ?) B) N6 o8 q! d1 |# A; @! }
. t! E0 z" d8 M/ Z
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;
* I/ o: x% i* L2 a1 \& @- v4 k3 c- z virtual bool CheckAndRefresh() = 0;7 E* ~5 {# Y/ p+ s# y
virtual void StopAsyncFind() = 0;8 b& a5 h- Z# T' y& `% N$ x
virtual void DeletePorts() = 0;6 M9 g, `! O t
virtual bool IsReady() = 0;6 w/ o, p9 F8 F2 z
virtual int GetImplementationID() = 0;
: l( j1 b3 c6 p" d' U* u
* }0 n8 W) f3 Y7 G. a* r void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping) F: U: R4 _7 u. f) a: ?; i/ F
! I5 j+ I, f, w+ ?% M0 ]# a4 q
9 N6 j5 t* A( o7 p void SetMessageOnResult(HWND hWindow, UINT nMessageID);
+ Y6 b' m+ g; U/ I TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }
4 `1 [, U2 X9 s5 o+ B uint16 GetUsedTCPPort() { return m_nTCPPort; }
% N5 k8 q, V5 |) D; A uint16 GetUsedUDPPort() { return m_nUDPPort; } 1 d4 F3 h; V8 S! u. j" H! k
8 ~1 I; ^3 Y% m+ t$ r
$ m7 j: }1 O8 M' j// Implementation& c* J, {! Q* o
protected:
5 h% L$ S& M' y9 s% A; `& u volatile TRISTATE m_bUPnPPortsForwarded;$ I/ \: q* q1 l* ]: U
void SendResultMessage();" L' b1 u/ s& T( P! L. @$ ~# t) C
uint16 m_nUDPPort;! |* Q. M7 P6 w/ B7 P. o
uint16 m_nTCPPort;
) u7 j- }1 f% L u# S# E7 m8 K uint16 m_nTCPWebPort;
3 g _# X2 W; z( n) ? bool m_bCheckAndRefresh;
, ]7 c! q1 E4 }* b
/ a/ d1 Q6 O! e* P1 g4 c! X& B; b$ P" e# ^& Y, `
private:
" f2 B: r4 L8 x2 v3 f6 ^) F; N, G1 D HWND m_hResultMessageWindow;# j3 \+ L6 E! r5 _; i1 l3 D
UINT m_nResultMessageID;
% C# L$ A- E2 I
- J5 X1 T4 W! j T; q* j- G- ~! @2 ^. y5 A
};
6 h+ n7 ?& Z' l% h( P
* U. p; E+ X6 g: W% N _4 d, c1 ~4 z
" ?1 l) I9 T1 b7 r5 y4 b& j! a// Dummy Implementation to be used when no other implementation is available9 W3 c- s8 @$ _; G- q
class CUPnPImplNone: public CUPnPImpl
6 ^& J8 F1 Z- T5 h& [9 q& o- a* a{1 E4 R. Z8 J) I( w* p) Q% ?
public:
' x6 w0 T3 u: ]. M% g+ F virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }3 v0 i0 Z, W' ?
virtual bool CheckAndRefresh() { return false; }& a; D6 i# M2 E# g$ D( R/ D
virtual void StopAsyncFind() { }5 M! Q, v3 ^3 d, d; S
virtual void DeletePorts() { }
M* x6 C. ]1 U% G: c virtual bool IsReady() { return false; }% y/ M- W! S* Q/ u6 k
virtual int GetImplementationID() { return UPNP_IMPL_NONE; }
: v8 p I6 v/ ~; j3 l% w};8 R- S4 q8 K1 E3 X
: e7 j' o3 \0 r) P6 i. |; D6 _7 F) @) i8 w1 P
/////////////////////////////////////: \$ _" G- z6 S* d1 G2 C
//下面是使用windows操作系统自带的UPNP功能的子类
+ A/ c& Z1 o2 Y
+ p Y& ]& b7 A. E) T" a/ F" _6 e
#pragma once
" A% u& O* T, q#pragma warning( disable: 4355 )
& \! U. R3 V5 }( H4 X* M
% T; k1 B4 b( u+ a
) f% C, ?/ K5 H- u f! g6 r#include "UPnPImpl.h"
/ k" c# c4 J& n; j#include <upnp.h>$ H( r1 n% a& A6 `" j. f' E# W" h
#include <iphlpapi.h>) I3 F! n6 `; y+ m* d' ? E( N
#include <comdef.h>4 g: A& H A5 A2 _0 Q: n; N# M
#include <winsvc.h>+ \' ]2 ?. u2 A# P G3 P
2 A, k# A5 J$ B- D; |: x- L/ e X0 X4 f: d0 u5 R& ~) ^
#include <vector>
- g8 S7 W j* x) O0 I/ M9 {#include <exception>
) }9 v9 r! t( N$ p% c. H6 l9 }4 K#include <functional>* f; a6 ~8 @2 Q1 E. D1 d
: c( z7 R0 r5 k
* ^! N( @% _9 e0 f. w3 H) o1 m+ w9 J6 k8 F0 D" l ?
9 U, q f6 n8 Z. `* V! Dtypedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;
! o0 j5 {- u7 |: B* \typedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;" }* _0 }. ]6 G4 \
typedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;
" l# B. ^! P' B$ k; p" Vtypedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;7 x8 e; A x: E% F% e/ u) ~* ~: b. P
typedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;
6 S* @( W/ m% i5 q7 F. d3 x/ Jtypedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;- Y' L( x1 {; d2 Q* o# V
typedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;8 g5 ^4 {# e9 w: w" v
" d, q1 A; a2 Q+ F1 }2 o
0 x! ]" J- j& V! I; a) Y+ `typedef DWORD (WINAPI* TGetBestInterface) (" t" E0 t( h* {5 r2 h# ^
IPAddr dwDestAddr,
- T" U9 t: b, b4 @' ^6 ? PDWORD pdwBestIfIndex
0 [: ]2 Y( G; @# x% c);* {0 |/ z+ ?1 c/ x% J5 D% a7 T
1 p/ |7 ^ X. A, `
1 v+ u5 O) `. V' l6 W' `! ~
typedef DWORD (WINAPI* TGetIpAddrTable) (
! ^) J4 r6 ]6 E* E: V9 K2 f* ~4 m PMIB_IPADDRTABLE pIpAddrTable,% D- Q% ?; n9 r( S6 _: F
PULONG pdwSize,! @/ G' F; C a4 s
BOOL bOrder
3 i2 E" M$ `! |);
8 b4 e9 f3 k0 v- [) Q+ q) G" d% a4 \$ U$ r" K
) ~" D1 I6 k/ F6 S$ H ptypedef DWORD (WINAPI* TGetIfEntry) (
9 {5 m- y E! x, h PMIB_IFROW pIfRow Q7 z, B4 W" ~$ I; \5 d& `0 ? v+ I
);6 `& f/ g! t! r# A) y ?
8 L2 p" l* p* B: w4 H5 s: L
+ P( ]1 C% d' b1 u; n, o
CString translateUPnPResult(HRESULT hr);
& D5 U8 f/ r2 d' y/ ^. L GHRESULT UPnPMessage(HRESULT hr);* e1 z( y$ I6 k$ C" x0 h+ x5 {2 s
! @6 Q0 V; y# Y* z9 x
6 s3 P. q8 U% e3 @, I8 z# ]4 Wclass CUPnPImplWinServ: public CUPnPImpl
, r2 w. Z: ~% P5 m+ [( u. V{
/ n: E8 B/ @, @' {* V. c friend class CDeviceFinderCallback;
1 ]1 m1 ^% Q! w6 s+ y friend class CServiceCallback;
; ^' n3 @/ k3 `4 I' `. \5 r. j// Construction
! p& B+ p+ M- l4 L& K1 A; h# x3 ppublic:
2 s2 r& B" t+ ? virtual ~CUPnPImplWinServ(); A% i& H2 W, y
CUPnPImplWinServ();
2 d# |) h, v: Y% Z2 v; a* u1 O6 U+ R* c) r0 E! _
1 a- }. w: _: t" c
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }
" y/ \ N' `# j2 Z) ~( v virtual void StopAsyncFind();" u1 P; n' P2 |8 q7 v
virtual void DeletePorts();
+ l* `& m# o& D; i- J! V: {: A virtual bool IsReady();
9 s7 U8 H' L- P6 ? virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }
, Z& k0 p8 K5 y; |$ k
; q: @; E+ J* m" P: g8 r
$ D, }7 ]) M5 k // No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)
% x: W" n) b( X7 O // the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later
. M4 c& J; { N! t+ Z6 [6 q0 G virtual bool CheckAndRefresh() { return false; };) M( E$ d$ b6 Y# `/ W7 q5 s6 Y
0 D6 N: A9 K& m) T/ G& c! W- x4 |1 s9 O$ M% Z/ ~; ^
protected:9 w, O+ O. y+ z
void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);
6 z7 C+ C) ^" d) h. A void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);' }+ v7 @" `# _
void RemoveDevice(CComBSTR bsUDN);& p- r8 G5 p: m% V. t
bool OnSearchComplete();
9 f. P+ M) P1 s! }# R. ~7 y6 C void Init();) s4 w" x: Q: w. D0 }. d3 @& v
: [; i6 t7 d6 Y5 I5 @
* k) t+ l# Z9 p& Z* t7 Z+ F1 ~& p
inline bool IsAsyncFindRunning() 8 ?4 \) y2 D1 D, D- {
{
& Z2 ^/ Y- K8 P) w/ ? if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )# \) Q( ]2 W4 P# t
{ s# }) ^9 I0 p
m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );3 r3 K# F0 a6 B! a
m_bAsyncFindRunning = false; S0 |% g* y8 Q4 \# \
}8 x$ T; d" v3 U V/ P2 Q: M3 t
MSG msg;
% q1 K3 {0 G9 }( a+ v3 z8 M7 W, l/ U3 O while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
7 U# c- m( y8 {+ u) V- D {
$ ?; w: V3 p2 R TranslateMessage( &msg );
) _% u8 V" z5 q6 W6 k2 v DispatchMessage( &msg );6 b+ {7 b. [0 w$ J' ?/ `- ?
}- U0 c, M/ ]9 e7 L1 t! ^
return m_bAsyncFindRunning;$ y3 p6 V$ X x+ r& m; d- f; I+ Z
}# u8 l# M0 y( U8 { O
5 c e0 n* V- t8 ~! a& Z* X
7 Q" h! O! p/ U( l3 _# f' H
TRISTATE m_bUPnPDeviceConnected;
7 y: s1 p) H# w8 v0 z" x
5 i7 `; u) A2 s! S7 k" g& {$ p5 Z* g( F( @+ V0 k+ w t7 b/ B
// Implementation7 Q- U) ~& m& p8 u, P: }" n
// API functions" b, z9 P5 L6 D j! E- _
SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);
' h1 u, P. K$ ~, I. r SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);
3 Q7 d G% L: _ BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);
1 D( Y2 r2 m$ p- { BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);
0 `. P% J7 ?3 n2 Y4 }- h BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);, b3 ^" D# g6 M, @8 J8 L
BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);; R* A. J8 j6 D r
4 U' p" T u8 o2 J' j/ q& ]
* r6 I; a7 _( [ \6 ?0 @ TGetBestInterface m_pfGetBestInterface;
4 A; ], ?9 z9 b TGetIpAddrTable m_pfGetIpAddrTable;
+ L2 } u+ N! [" [ g" c& D TGetIfEntry m_pfGetIfEntry;
" O/ y$ _9 U; J
F4 N6 b2 T' t" F' s9 }7 u# |6 u8 g* @
static FinderPointer CreateFinderInstance();1 c# U- z: I% ?7 M3 N) c1 S- q
struct FindDevice : std::unary_function< DevicePointer, bool >! N1 t8 {& f8 Y; i! t
{- ?; ~+ a9 o; [" h2 D5 ]( `
FindDevice(const CComBSTR& udn) : m_udn( udn ) {}
! ~% b, k- d- d result_type operator()(argument_type device) const. _& y9 g3 _6 y
{
3 S! E# M3 }2 {' v/ [ CComBSTR deviceName;
( N( p& m2 d4 r n/ B1 ]/ `" s9 v HRESULT hr = device->get_UniqueDeviceName( &deviceName );7 e1 I3 Y e& x6 @ z) S5 f1 ?
" a1 l* L5 ?0 T+ C2 Q& D" e/ W
& M. G5 @" X) z, m if ( FAILED( hr ) )' i: @( \' B4 z/ F
return UPnPMessage( hr ), false;& J( m4 H) I% q, T; a5 o6 w
' c! m+ b( G% h8 v2 W! L& r" }7 t; g
return wcscmp( deviceName.m_str, m_udn ) == 0;/ c% J& m& F! Q8 B4 X! z: _5 \
}
% I2 j% n8 L( W) ]' _8 _ CComBSTR m_udn;) }3 h, {+ H) X1 N% `) B
};
7 i: E$ p Z! d. ^# V 3 [0 J! w& Q8 J1 `$ G9 B& V- V2 m( G
void ProcessAsyncFind(CComBSTR bsSearchType);; H. n; @1 q1 A7 {. X
HRESULT GetDeviceServices(DevicePointer pDevice);
4 \* m9 _1 V, `$ d) B void StartPortMapping();( D* d4 M; b& w0 y' [
HRESULT MapPort(const ServicePointer& service);
% z4 V# n/ b7 C/ n1 M. M void DeleteExistingPortMappings(ServicePointer pService);: \* N/ q5 }5 T" f
void CreatePortMappings(ServicePointer pService);
: Y; w$ j6 }0 Z HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);8 ~$ M/ {6 O8 f/ S( B
HRESULT InvokeAction(ServicePointer pService, CComBSTR action,
( q) b; B9 \. Q LPCTSTR pszInArgString, CString& strResult);
! u' j) {$ R# e4 V9 M void StopUPnPService();2 Q& \* a! \/ v
9 T4 x0 [9 j0 @$ U
) a$ o' ?; R+ d' z/ Z // Utility functions
. b7 A! ^+ i: o: Y' T, e* D% H! T HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);, P# P y% b" j( ~) _# e* {
INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars); ~; x/ {: O% ~' n# P7 Q
INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);0 s6 e6 s- l3 I. t1 S5 R
void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);
/ M s( y7 b* B* g$ Z$ i8 W8 @6 } HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);
# i6 d5 B' I' |* W5 U HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);2 _- |. e- r0 ?0 N7 p" z
CString GetLocalRoutableIP(ServicePointer pService);/ a8 b* q c+ w* X5 H8 B4 q
. K) b: U1 q7 B- s, @: Z) j0 @
: }; U. C3 k* b# @* i
// Private members) J; `# u* a5 r2 t
private:$ u7 d7 ?& ]3 d8 n8 m/ ^/ Q
DWORD m_tLastEvent; // When the last event was received?7 ~! n0 I& l+ G6 B6 W' r
std::vector< DevicePointer > m_pDevices;# Z* U3 F2 V" H( s+ M2 E8 {9 J
std::vector< ServicePointer > m_pServices;9 L4 x! I0 H/ C" s! P
FinderPointer m_pDeviceFinder;) W. [/ \3 L# g! u }. @9 ]
DeviceFinderCallback m_pDeviceFinderCallback;4 w. \' G4 N0 B
ServiceCallback m_pServiceCallback;
Y* l+ C& J) O5 T; L3 |
& W/ ~4 x) j9 k2 h8 u) T6 |/ G8 u! I j3 W' v f$ k2 ~, X. z
LONG m_nAsyncFindHandle;
1 E! p" Q" Q @' G9 I bool m_bCOM;: [1 m9 E; M: V' ]
bool m_bPortIsFree;
7 Y4 S( n# |5 o& k CString m_sLocalIP;
6 ~4 |! ^7 P) A9 D CString m_sExternalIP;: v. z, h, \; x" P
bool m_bADSL; // Is the device ADSL?+ q7 b v& D9 n. o
bool m_ADSLFailed; // Did port mapping failed for the ADSL device?
1 j9 u8 n: R2 P2 ~2 c6 R bool m_bInited;: n# ]$ w, v% f3 O
bool m_bAsyncFindRunning;
5 z4 i1 H. X: X HMODULE m_hADVAPI32_DLL;
' I/ }+ t5 p4 I HMODULE m_hIPHLPAPI_DLL;
) u, ^: ~# E& g. T3 D bool m_bSecondTry;+ e, w9 a0 B4 m* u
bool m_bServiceStartedByEmule;
" z$ l. N8 F/ }/ ^1 F, N7 s6 U bool m_bDisableWANIPSetup;
3 J& [8 B" }0 j- T7 M bool m_bDisableWANPPPSetup;
( |2 y/ Z( f) E, Y! ]( z% r: n7 O4 W
K, t9 x" v: q9 L& R' T
};' g/ }1 g( ?# Z0 S* ^" N5 U4 x
0 C3 p+ Q5 d( f2 [, L6 I- L5 R$ ?( b
// DeviceFinder Callback
' C4 ] t) M8 D, u5 Nclass CDeviceFinderCallback
3 O' ~) R# v1 ~8 o$ ^; k3 @% B : public IUPnPDeviceFinderCallback
: k0 j7 Y% h4 o8 U{" A& }+ I, ?) [4 b/ [
public:6 X* L/ N* V: \ P/ w
CDeviceFinderCallback(CUPnPImplWinServ& instance)
w$ f9 |$ w0 W% F7 i; ^9 d : m_instance( instance )) W, b$ n/ M' I
{ m_lRefCount = 0; }/ a. q& w6 s" f
" `/ v k- r+ Q- r0 [# s, S$ T" C
0 V8 V' Q. u1 S' ~8 a$ ] STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);5 h) H0 }1 N$ e
STDMETHODIMP_(ULONG) AddRef();3 Y4 W; o! b; X2 p+ n4 x
STDMETHODIMP_(ULONG) Release();, n# x0 ]' n$ E8 t# A% _# g
, Z4 f; I- g& i0 B( ~2 U3 n
/ E" K& e5 F$ r# s3 t// implementation( z8 }- W2 J8 o& R$ {7 o! r& o% s
private:) R" O* W- b5 ]2 x4 p0 x& [1 G( t. ?
HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);: S9 V* G* c1 k/ {! m
HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);
2 ?* y% a, s% Z! C# } HRESULT __stdcall SearchComplete(LONG nFindData);3 _, g, a, k. X# B
; L; _4 Q* n, @" Q0 d1 P/ [" g1 J2 ` |9 {' X
private:6 w( p$ G, {8 C4 e4 O( n2 Q% G
CUPnPImplWinServ& m_instance;& w: R3 s3 ]9 ^( p6 X, E, ^ d
LONG m_lRefCount;
% n9 w4 k# m! u" `' \8 k& W};
- K6 F6 O8 ]' C8 x3 v2 {5 l- O2 ]) `- C7 m; `
# O* x% d2 T0 ~( B6 U
// Service Callback ( N7 r3 C6 d1 ^# x3 d3 W
class CServiceCallback7 E' J4 W$ c1 Q2 M! ?
: public IUPnPServiceCallback
" _" @: [/ S9 Q{
7 N: x4 `8 H0 W9 N9 c, Spublic:
4 A& t+ O% b1 i CServiceCallback(CUPnPImplWinServ& instance)
1 [9 E/ q% Z2 `, B( I, o6 g# I : m_instance( instance )
& l' M- {4 S: r8 w4 F! H { m_lRefCount = 0; }. u3 e5 i/ O0 b+ \- ]
# }% j L; P8 O7 m$ j. ~ STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
! t8 ^5 Z) a: B; i STDMETHODIMP_(ULONG) AddRef();: Q6 G7 F6 `8 h6 K7 F1 Z7 v( a3 N
STDMETHODIMP_(ULONG) Release();$ A2 j8 m4 y8 f) f1 n
' y; o& ?) V$ M; ?* Z. A# |$ P0 \
4 c! Y$ M! h7 r' q
// implementation
6 |3 h2 b% m% {+ Dprivate:
9 f; v# O \' X# K HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);6 `3 P- Y/ b/ M, v: ?. U+ \
HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);7 y# _3 c& W6 a6 V
3 a$ ~. R9 \% G
. G- G: T, V; Kprivate:
( D1 j/ m8 c% v0 H% A CUPnPImplWinServ& m_instance;
- F) A; T8 v& e, }" F LONG m_lRefCount;
/ e7 ], M! S/ k2 t};- _# c/ Q& m a" z
! S( ?7 F# f; L1 z" N- U$ S/ o/ V/ A2 Q
/////////////////////////////////////////////////
( Q5 {8 s1 x- E6 l1 Z
# a, C$ d' `9 X A0 f) W
% A5 `# s( n! P* ]0 d; M, t5 m使用时只需要使用抽象类的接口。7 G# Q) J7 S% |* @6 p
CUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID./ D L! x0 ?3 n0 n
CUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.% e `+ D/ f f# @, _
CUPnPImpl::StopAsyncFind停止设备查找.
/ R8 v5 a) f* w- rCUPnPImpl::DeletePorts删除端口映射. |
|