|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule,. e2 g% `8 {; h1 M
, f: b: w" c) }& b1 ~) w
( B* c3 n: H4 Y1 W" l3 E0 S) ?! B, p
///////////////////////////////////////////
. B1 r4 h, _& q0 x* ]$ R//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.
7 Z2 F" W7 g7 C3 T' U) Z- W
- ^1 a( E: l" B) m% E( m& [* u% x G
( B( z7 [3 E( O. \, ^1 H8 [#pragma once
8 w: x3 Z B& |2 `- ?#include <exception>) f1 [2 u+ N' a
5 k/ u6 F& E9 {9 r9 `1 o0 q6 F
7 @9 \# w! g3 Y ?5 @5 z enum TRISTATE{
4 U1 w; |" d( _ `6 I: l TRIS_FALSE,
4 ]* d2 I/ w% s. }, v8 H4 C0 v' } TRIS_UNKNOWN,
5 _( }( s4 N! }5 [1 ]0 Q TRIS_TRUE
; j; z+ j8 |; _; \! u};
9 A( v k- k; _
8 n/ \6 e, g O5 \! x% j7 F1 u z, r8 i
enum UPNP_IMPLEMENTATION{$ H- r; _* n! U, f; U0 b
UPNP_IMPL_WINDOWSERVICE = 0,' a% _) D/ O8 c! a
UPNP_IMPL_MINIUPNPLIB,
5 n2 l2 y5 _* P. i! \. z( P& ` UPNP_IMPL_NONE /*last*/4 r- x5 x+ o$ y* O
};' ~7 {. D5 q9 u5 F! f! A! `
+ v7 V( q, h3 r7 w4 U3 K! }9 U, g& h' T8 m* d
( v. {" j3 w3 u' ?3 f
; S0 |& G: U- @ h( K) `/ h8 mclass CUPnPImpl
2 L5 K! x; K" L{
9 ~8 c. K* w8 O: Fpublic:& s% ?& O- T7 a9 q/ ]8 G7 h7 {
CUPnPImpl();, ]4 X9 R4 z# ]! o5 o& u
virtual ~CUPnPImpl();9 q) H- u3 T, M8 \: i9 R) O1 w
struct UPnPError : std::exception {};) j4 Q/ v4 e6 o. l4 c$ K2 E$ [
enum {+ {& \- z+ \- d. p, i7 Q$ v' t
UPNP_OK,
2 M2 M( R/ X0 l; ^$ N UPNP_FAILED,8 {# a/ X8 E" f- ?1 s
UPNP_TIMEOUT! g$ }2 H2 D2 o$ l. }
};% l: y) W( I( J: M
$ I; L" E/ E8 p7 T- l
, E5 \% ^% d$ G6 b, P9 w virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;
3 Y( C& b! d+ p- h7 z virtual bool CheckAndRefresh() = 0;
4 L! ~5 v: c' s; R7 h8 i" I virtual void StopAsyncFind() = 0;* P" z# }9 n. z6 q, T, G1 U" h& x
virtual void DeletePorts() = 0;
' r1 J+ J! R! | G0 n virtual bool IsReady() = 0;5 t7 F& G$ U' O3 u; \
virtual int GetImplementationID() = 0;8 h8 G0 t; u) }& g6 ~
/ ~/ s: R# u) a$ Y* C void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping
7 P$ w9 u5 r r7 P' P3 O- e5 w4 Y9 u# O: K j! X) W
, E% H2 _9 S. @9 r3 o$ d$ L
void SetMessageOnResult(HWND hWindow, UINT nMessageID);( d0 [: S5 H7 q
TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }
: o8 [: N' T6 D6 f( t' B uint16 GetUsedTCPPort() { return m_nTCPPort; }! M* G3 s/ C6 K
uint16 GetUsedUDPPort() { return m_nUDPPort; }
+ |, V6 b# T' z: ^+ T2 r2 h, P: Z _" R- M7 ^- N/ k
: [ ` ?4 |1 Z// Implementation
8 z' Z) s2 N5 ^! K6 Sprotected:) ^- O( n& _' v7 w L4 @; u" P
volatile TRISTATE m_bUPnPPortsForwarded;
9 _! p3 s" H. V. r! S# q void SendResultMessage();
. I2 ~4 |4 [2 }3 H9 G uint16 m_nUDPPort;
& E8 N7 r& l* g' v3 e( P uint16 m_nTCPPort;
6 [8 |/ E4 W p4 b) d; g uint16 m_nTCPWebPort;
- a9 J! Y3 Q& A" B; ^. m% \ bool m_bCheckAndRefresh;) {+ P' r+ b/ N/ G8 n
; B+ o6 q& A+ C* U6 G( t3 L/ H4 I/ q1 w
/ v' f% n, I8 x& z1 T, Z8 K3 Hprivate:: G& E% q' p1 Y8 ~% N7 I
HWND m_hResultMessageWindow;8 ?) N+ F& O! Q1 k. `) r& u
UINT m_nResultMessageID;7 i- Z# w# S8 F, {/ b% ]# h) O
4 |3 Q# g$ [; u# H& b+ A
+ a5 u9 |/ R# z: ~};0 S* y4 E# i5 E* q: d
- q \0 X2 J, S4 \+ y1 t& [: q* v& a) E5 }
// Dummy Implementation to be used when no other implementation is available9 b) ^+ S) D, G& M8 S
class CUPnPImplNone: public CUPnPImpl
: ~) e6 y% D; q4 X! S{) N* |' c* B! m _! v D) l
public:
6 x" U$ t( U% { virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }
4 P1 n/ X: f3 b' n virtual bool CheckAndRefresh() { return false; }: }& P' T( O; ? p0 v, t" M0 P; I
virtual void StopAsyncFind() { }
) l; [7 [6 L. a virtual void DeletePorts() { }
& ?2 R y. \' r1 X$ L virtual bool IsReady() { return false; }
- N, e1 V: @: M& I( N4 A virtual int GetImplementationID() { return UPNP_IMPL_NONE; }
8 b" q" \2 V+ m) ^4 M5 N$ J};
- ^$ u! j" t0 Q$ L+ I( w
) c3 H4 f" V: A. V [! {5 X" K; n! [& z0 s1 Z
/////////////////////////////////////" ~, g) ]* q3 Y8 k t, X0 q
//下面是使用windows操作系统自带的UPNP功能的子类
) o2 S: k) X+ W s2 W+ F" B
# m# @5 H% I3 s6 [ }! ^
* ^& [- i: P4 U9 I1 C#pragma once
- P" J/ g6 j9 E3 F( g#pragma warning( disable: 4355 ). r4 q+ _: }. R: U8 e9 l
- `5 {* N7 ^- Q+ |# t) J2 X. _
2 b9 ?( s* n7 O. A. g; L
#include "UPnPImpl.h"
" _ p6 W, b7 i) J. w+ h$ K#include <upnp.h>0 m$ R4 a6 `) [" }1 o' I
#include <iphlpapi.h>
# Q0 R a- D0 P; I! l9 l#include <comdef.h>
( H; t- H0 s2 k+ Q#include <winsvc.h>. x7 X7 E, w, P+ j& ~
& v/ x8 V% |% f8 `: y7 A
; e0 }& h @1 ]$ {+ s+ p
#include <vector>
% V4 p ^" \& N#include <exception>2 \& |" e- T5 h( P w7 c# z* k$ m
#include <functional>
& M' y9 I& e3 @& ^+ L* B- i! c$ w6 Z8 l& F! l
- J7 \! }' ?5 t1 r3 n0 K( A- `7 M- c5 e. `$ R
2 D2 h# L3 M/ f% c, `2 Z0 Z) p7 Vtypedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer; L$ |* P9 D1 I, o( D2 h
typedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;! Y0 q( c: ]3 q( B9 y
typedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;- m) ^: f6 d: ]
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;7 a3 r8 J+ s& ?3 Z# r/ J# ~
typedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;7 D) |2 e( x0 D4 J# y0 k5 q" D
typedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;6 X9 `5 j, c5 |6 J2 G3 W2 L
typedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;1 U# Z' G3 w, i( P+ Z
2 l* { j# q |) F( a
. k7 U0 F% g( y" u9 S
typedef DWORD (WINAPI* TGetBestInterface) (
$ \1 w: r- D4 {# W8 V. n) m IPAddr dwDestAddr,( I. Q4 @2 F; i! }! p
PDWORD pdwBestIfIndex7 h9 e h, b& i- K! O( f' ?
);
8 F* |. F, Y, f4 d( M: v+ H0 t/ A2 c& Q5 e* D8 p
?2 Y/ `) H1 stypedef DWORD (WINAPI* TGetIpAddrTable) (
) F) g" v+ T* U PMIB_IPADDRTABLE pIpAddrTable,# i% `& F$ g' L
PULONG pdwSize,: O; {5 p+ _. n
BOOL bOrder
9 J2 f6 J+ l5 z* ^7 s, a);
; c/ T6 `' k9 ]7 @5 m: V, j' f! D; D5 [# G* S6 ~% l
: k) r6 P9 `. ]# r7 V
typedef DWORD (WINAPI* TGetIfEntry) (' ~% e0 z9 a* z1 {+ w. b
PMIB_IFROW pIfRow
! b: r1 X, u- p2 ]);6 {6 q2 _, \& Q! H' d) q0 h
% A9 o' R: [: g+ {0 U; A4 [0 P# r+ Y4 q$ F0 l+ P, N
CString translateUPnPResult(HRESULT hr);
( L6 l/ {; y: f2 x& GHRESULT UPnPMessage(HRESULT hr);
* m9 g2 O% w/ L3 [( g7 R" e- V: E) w0 I- W+ x0 U
9 H- X# i+ u$ ~( n+ l* rclass CUPnPImplWinServ: public CUPnPImpl
6 _$ w: @0 U3 M" n' \# t* A7 B2 @3 }{
: Z) V5 J2 r% ^ friend class CDeviceFinderCallback;6 p# k% v' }8 t, ^: D7 O
friend class CServiceCallback;
/ f6 E- C8 E5 }: ]8 u9 n# e) N// Construction' B% Z4 a1 h! R9 @9 X1 f
public:/ Q) k; G* F m) t' F' y
virtual ~CUPnPImplWinServ();) F3 q, W1 @9 n# @* F
CUPnPImplWinServ();* c& K9 r# K& J& |* R. q
% o* I7 [! s) H2 p& a6 ~! m" i7 w% K" o y4 O8 x
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }
1 b" h* `8 {+ e/ P virtual void StopAsyncFind();
) z& w6 Q# t: ~7 M; L virtual void DeletePorts(); ]8 g( i$ i, z! B1 R6 a
virtual bool IsReady();
" Y9 k2 v$ K9 S8 V virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }
; o; U) n1 } g, W- {; S$ n+ r
1 g# y. i9 B% @+ \ N4 \* F' A Z" n4 N2 k V
// No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)
9 ]/ Q& a/ n2 e9 P3 v" N4 g // the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later2 f& I2 r8 ^* E( \
virtual bool CheckAndRefresh() { return false; };
7 a2 z& x. X5 ]
: P/ y& [' F! B2 b+ G w6 R5 x! g1 C9 W8 v
protected:, q8 a6 w4 h- s) S5 S+ G- |
void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);5 c: s9 q" x$ }+ s+ B
void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);
& |5 _* S% O& p E$ Q void RemoveDevice(CComBSTR bsUDN);
) Z4 O( T; v% m* m bool OnSearchComplete();
! d" _4 U$ V$ q* n void Init();
6 Q n& k! J3 |' R% J5 n! `7 Q, S: D9 e# m& ?7 b v
! P( a V( o* I inline bool IsAsyncFindRunning()
- C5 i& p3 Q& G& X { Y* W* u' \( w% W% N* Q: e
if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )
v* t- k+ s+ v {: M6 q4 l* G* D& h% x$ j4 w
m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );
" p. H* t7 Y# T$ Z m_bAsyncFindRunning = false;3 i! m1 @. c3 k! N: e) D9 h' e
} ^0 C1 O1 {, U3 K
MSG msg;
7 k. F/ B$ D5 y8 l* x' J while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ): b R# V) f- @
{
: p+ J$ Z5 P& R+ K5 K TranslateMessage( &msg );: B$ G! r6 \! @& ^0 b
DispatchMessage( &msg );9 W9 g, s a) n+ T
}
3 X+ I' A2 T* \! v1 |8 ?, q return m_bAsyncFindRunning;$ d3 A6 }8 \( i- E$ o: W
}
1 y' }" ^/ n. O5 }
2 }0 \. z, U" N @" ?" f2 ?* ~: M
TRISTATE m_bUPnPDeviceConnected;! n4 @5 u$ }7 R6 z* Y( T7 V
. Y# i' ?; N( h$ [4 r+ J# |6 a6 D% m. y3 {0 T
// Implementation w0 J7 Q6 K, @* ?
// API functions# j% t5 Z" U! d. v' ~
SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);
" N% L7 L( X; F" I5 A5 g, k6 ~ SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);. B) `& \ [! o$ j. s
BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);! l% u. v0 O% e% K
BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);
5 Z, F) |' M, \2 I' y BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);% S# `6 g$ {% E: Q9 s
BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);
. d7 z6 S* l+ u) q; }* i! c+ m( k$ [, O! B/ b1 t2 U( z6 B
+ r7 U S- {5 t' I' h I TGetBestInterface m_pfGetBestInterface;
$ V- ^# d1 U, x+ O" E$ x8 Q+ q TGetIpAddrTable m_pfGetIpAddrTable;
) m t/ {3 E" U K5 E; E( A TGetIfEntry m_pfGetIfEntry;
" d% Y% J5 N* R. f4 x4 o
* m: M4 U8 r; N: C, _" j: ^/ O. m7 L1 A1 J
static FinderPointer CreateFinderInstance();
! I2 I$ P( G& m% J, K6 g7 |3 [ struct FindDevice : std::unary_function< DevicePointer, bool >3 u: W1 x8 s& d+ @3 ~1 b
{
" w; g, i! F+ f4 w& }1 s FindDevice(const CComBSTR& udn) : m_udn( udn ) {}( w1 |# c. f* ?" H* G
result_type operator()(argument_type device) const
# L$ C, |( p4 c9 C0 @0 N {
& u* t; [1 U7 a% q6 J: o CComBSTR deviceName;
5 j/ z( n8 ?8 m \ _. y$ f HRESULT hr = device->get_UniqueDeviceName( &deviceName );
, i- c0 z6 q3 _
* _: v0 B D, W6 G- e- X6 c1 d c n7 y# q" f- J0 H' Z
if ( FAILED( hr ) )/ p1 j7 O/ p9 W
return UPnPMessage( hr ), false;$ u% K% `! G- ~9 V2 V* k
" `8 |& d* V% r; p& @" e G N1 w8 U7 k
return wcscmp( deviceName.m_str, m_udn ) == 0;, U) k" w* q5 Z$ j
}
8 l' U) [4 H5 j+ l& }& b4 n# M CComBSTR m_udn;$ u$ Z t$ n- h
};$ x5 t% [ u5 ]( W$ P) g- |
; p; \4 O9 h' L& @/ J9 ? void ProcessAsyncFind(CComBSTR bsSearchType);* G' j; x* z" a" b* t/ r. M
HRESULT GetDeviceServices(DevicePointer pDevice);
4 e F' E% B0 P0 U7 Y2 O void StartPortMapping();
: S. X/ P. Y2 K9 K6 q Z' I HRESULT MapPort(const ServicePointer& service);
6 c# N- [+ J' ?6 _# m% b4 r void DeleteExistingPortMappings(ServicePointer pService);
8 n' g8 D% B% a& h* i& x% Q" H& b void CreatePortMappings(ServicePointer pService);$ J3 u+ H$ x7 K+ }5 F
HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);# }' s. s7 c& ^8 u% L) k$ }# _
HRESULT InvokeAction(ServicePointer pService, CComBSTR action, 9 r2 ^% n5 C& f. ?0 \5 B. D' L
LPCTSTR pszInArgString, CString& strResult);
# s- O! w% N* E void StopUPnPService();
, @9 \- m$ W9 C3 _( o. e( W2 y: [$ \3 M! B* a6 p% o0 Y+ Y. G
0 i& q" X% L2 Y4 h
// Utility functions' [# i: z- y- w$ _. Y+ A8 M
HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);. c6 C! p; `2 s4 d, M
INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);
1 j5 J0 y% M% u% x: Q/ t9 l+ V INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);
) E9 w- O4 x) i8 G void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);3 j. Q7 F% \1 A' T
HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);
# l G" X4 G) A& F1 I. V' ] HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);
! ]. P" G: h3 T' W# S# V: Z- j CString GetLocalRoutableIP(ServicePointer pService);
' T3 I) V( c# X. K! Q* Q
/ v5 c8 l- f G7 K( o. j
. [4 q _: _0 K! |: @// Private members( ^& C( [) q% N( K
private:1 x6 }: r# p. c5 e& z; X1 _
DWORD m_tLastEvent; // When the last event was received?/ Z' G$ ?$ |( C
std::vector< DevicePointer > m_pDevices;& p: S+ i2 n: P& q7 e5 Z
std::vector< ServicePointer > m_pServices;6 i# d0 l7 a( l( B! A" ]
FinderPointer m_pDeviceFinder;5 n, O+ D3 I2 r/ e- G4 N
DeviceFinderCallback m_pDeviceFinderCallback;9 j6 L( ^8 B) {) `; w* @/ T8 s8 N
ServiceCallback m_pServiceCallback;: ]+ R# o7 d6 T; ]4 s6 O6 Z
5 m3 C( Y3 K3 U/ Q9 s( B
6 p5 h; \; n7 E
LONG m_nAsyncFindHandle;
9 A1 o! B- R, I# ] bool m_bCOM;
7 P+ T' s6 Y1 _* a bool m_bPortIsFree;) F- O+ f9 a* Q3 E$ ?# }( Z, ]
CString m_sLocalIP;) D6 q* ~7 y) A, ~8 R7 O
CString m_sExternalIP;
1 O7 \' {4 B* A/ M- b1 B bool m_bADSL; // Is the device ADSL?
2 }( r9 R: Q7 O2 a6 I$ T bool m_ADSLFailed; // Did port mapping failed for the ADSL device?4 M4 X8 s1 B8 e# A. @8 ^
bool m_bInited;
5 T! I- z+ a& N, B- d bool m_bAsyncFindRunning;; A M" N! X" l/ I- {: V7 C! }
HMODULE m_hADVAPI32_DLL;
% v% H; ^+ T" C u5 W7 k HMODULE m_hIPHLPAPI_DLL;/ N3 O) o* R0 G. E
bool m_bSecondTry;
/ p, P* n Z4 h0 k bool m_bServiceStartedByEmule;
2 K0 K/ ^3 c) [ bool m_bDisableWANIPSetup;& K, L3 E w' W6 D3 }
bool m_bDisableWANPPPSetup;
1 @) q% S1 J' \5 K2 W$ i
' [/ F9 B8 s% J' S7 i9 S2 d& }
8 n" v: G( }( V. I% [" u, Q};
& z6 k1 Z& }; s" E: g- z* R: C1 K9 d. R% o6 Z5 w/ ]3 T
4 _) u% g$ P# K* p// DeviceFinder Callback" e; \5 w6 u2 w1 f* Z
class CDeviceFinderCallback" \! p1 M3 K. Z8 ^% b& P% f
: public IUPnPDeviceFinderCallback
& M# o: W( ^) q3 z9 d0 r* @ ]* r" [{
# o& W( d+ |$ N5 |' f3 Gpublic:
6 i3 G9 ]9 }: c7 I: ?; k/ H' X J CDeviceFinderCallback(CUPnPImplWinServ& instance)) W9 t$ S3 \; [: y. b6 l
: m_instance( instance )8 X# W" T! k( W7 s
{ m_lRefCount = 0; }
( W! ~! e8 V& l+ O
/ f& |$ {; w. m" L+ p+ m1 J* A) z% w/ h! O
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
7 V& `8 i4 g* ~! F STDMETHODIMP_(ULONG) AddRef();( q' l( X5 ] u" I" g5 \
STDMETHODIMP_(ULONG) Release();
9 R1 l0 u6 u( ~
1 s' Z# V0 r9 b' k- h6 a3 J1 _$ n* D" A) x5 }/ W; T
// implementation, F) {$ H# X- |1 B' G$ e+ I
private:5 v2 E: G( [3 g! L+ W+ N
HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);
" d1 @, A- B' D, z0 z HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);
0 a; u/ D1 X6 L0 }$ F9 ^9 x5 f- o HRESULT __stdcall SearchComplete(LONG nFindData);0 A) h1 l3 Y S! P' ?( @
) q( m) K) z! c; b5 v5 G7 W) D
0 r/ T/ f8 i( K# C) T! \# c
private:
6 Z$ e1 [/ M0 A( I V1 C# A CUPnPImplWinServ& m_instance;" T2 @7 ~/ h# }- y8 _' C- f& r! P
LONG m_lRefCount;% _- P8 H/ z4 C3 J% W1 ]3 j
};
* Z+ N% D8 C0 M1 D! u6 R. X( O* Z! E- D7 ?
% S8 M6 Y! D+ G) }9 `// Service Callback 8 K$ `( l5 `. |( j4 g4 C3 t8 D5 c
class CServiceCallback
; B8 ?. Q, l2 S2 J6 i: j : public IUPnPServiceCallback
/ I( S1 G2 z1 R% K& S0 {{( A! u1 d) A* ]3 y
public:% Z& l, O4 N0 Y+ W! a$ Q
CServiceCallback(CUPnPImplWinServ& instance)* U; A7 t$ ^, O z) q- Z
: m_instance( instance )
9 x- i% e. e% \: S { m_lRefCount = 0; }
! z3 r7 M1 m/ P- n1 P3 }; \
8 r- z9 ^& }- ? A0 w STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
]. \4 g C7 [ STDMETHODIMP_(ULONG) AddRef();2 [" | g* T* _2 k" l
STDMETHODIMP_(ULONG) Release();
v* T& S$ Q1 s- ?6 V# e6 V1 _) j0 c0 p
( r9 ?$ ?5 j. }
// implementation
" m, M; N4 h5 C# g) n% L8 iprivate:
+ \4 f/ u) \3 i- G. r0 _ HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);* d. m% h% o9 l3 r0 S9 z
HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);" q- F1 G% @- N+ e2 D
! ~ k8 e1 b- [$ y4 m
' U% J/ k% q% Rprivate:' W6 ^+ m H& V, C
CUPnPImplWinServ& m_instance;/ a& Y' S7 \: t- h0 F) |1 _
LONG m_lRefCount;2 j9 V+ X* F9 v8 A* t/ q
};
8 ]9 e b) t8 x. a
( l- r8 f4 R/ Z" s. g! d+ F
7 @& j4 q9 q- j3 }/ N9 l/////////////////////////////////////////////////& F6 H; h3 _& H6 H9 u9 _
2 X- B8 X, C9 k& R/ R, x6 v
, X; I! r+ r% M; p# A使用时只需要使用抽象类的接口。
2 p( i" I4 K/ R! V0 KCUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.
/ r* X7 I0 } s) |* RCUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.
- o+ c3 K% ~$ ]& O1 |( R5 LCUPnPImpl::StopAsyncFind停止设备查找.
- R& V7 s' B6 W7 M! W' [7 BCUPnPImpl::DeletePorts删除端口映射. |
|