|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule, y8 _2 p3 N8 G) F' q, ~6 K
0 `: _" s' s5 G. V/ i
/ I1 x+ Y2 d: E9 U0 ^" B
///////////////////////////////////////////
$ L J( F$ N- a# P9 Q) J- Q//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.
0 |( S' g8 G; F2 Q0 P7 E
- I1 }1 j# y" z
) m* k5 D) P8 B& L) v#pragma once
' E0 e) Y s# B% K9 n$ V9 n#include <exception>
: J: `; Q5 O$ G! @3 z( q- Y' z
$ {# _$ v0 s/ C: A0 b1 G9 f# q" M: E6 z# Y% k& v6 [
enum TRISTATE{& L6 C- _8 S) y, h3 \
TRIS_FALSE,2 u' r$ h( z% G B% ?' x/ S
TRIS_UNKNOWN,4 q. E& F% e7 C
TRIS_TRUE
u. a; w0 M) I};) T5 ^8 N4 [ A9 |
H& h8 P1 B3 J/ G
1 S1 p" [# e6 K5 ?$ Y) L
enum UPNP_IMPLEMENTATION{6 |/ C% R3 d+ U) {# L( k, t
UPNP_IMPL_WINDOWSERVICE = 0,
" W3 u& y! z# n/ ], z UPNP_IMPL_MINIUPNPLIB,, I" |0 P* D4 ?# I
UPNP_IMPL_NONE /*last*/ ^. ^/ l2 a' y _, ]3 h1 d/ D
};# k$ C+ Z8 x) _' k8 C
- i5 e: H+ i. t9 v& P- ~
- X' l) T, u" s- ^1 G, y/ v4 s& w- w+ M
+ n. v4 s# L' S- X c7 Y1 gclass CUPnPImpl4 h/ p5 `* ?3 W* @/ P: ~
{8 h* A+ t+ }6 t2 q4 v6 S( w7 ?
public:
: {6 {3 }, T. f) P! T6 q CUPnPImpl();
( C/ s8 N/ q1 ]! D! M3 O virtual ~CUPnPImpl();( U) t4 y( M G9 h) D. b- H: Y, j
struct UPnPError : std::exception {};4 k4 |) _% @: a
enum {
u' L6 N- E) L) l; [1 ?+ c UPNP_OK,
( R, v* n; C, J UPNP_FAILED,, f! N. j! R5 n! c
UPNP_TIMEOUT3 w6 a% ?% ]# e
};
. \2 M/ ? W0 p; o# o5 u" B5 z+ S# @5 M. E( E/ f t6 c- B" o6 m5 A, r% r
0 |, U6 D" _9 } y. N( F
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;
% {9 H+ d: O- i virtual bool CheckAndRefresh() = 0;
' s9 E4 i- T+ G" d# V/ |- m virtual void StopAsyncFind() = 0;
) d. F0 e% |) e, K$ f4 p virtual void DeletePorts() = 0;
* Q7 r! \' ^/ t2 n. m! h: e virtual bool IsReady() = 0;1 t I/ w" ^0 q7 H4 X! e
virtual int GetImplementationID() = 0;
h7 D/ P7 X; c$ B: p
- V4 g- d# y- p8 D1 v void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping+ Z/ f' r0 Y$ j9 D9 x
9 t2 @2 I% I/ I, o5 e. s" @4 T
) @# \" g* f4 W9 t* X2 U
void SetMessageOnResult(HWND hWindow, UINT nMessageID);0 y0 j" T* D$ B* H9 C" r
TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }
, b0 W: o0 d2 H* a# C2 R uint16 GetUsedTCPPort() { return m_nTCPPort; }
& F* u1 r6 Y! o. U( n/ E' Z uint16 GetUsedUDPPort() { return m_nUDPPort; } : x8 C. c+ ]' z
5 T" E4 v/ A* w. D$ B5 a2 \" l2 P4 o, y
1 K* v7 J% s+ t/ m- v// Implementation
/ m0 M, ?3 }9 \' m* Y1 Uprotected:: o) M) b( ~2 C
volatile TRISTATE m_bUPnPPortsForwarded;! D7 O7 b9 B' u/ [9 Q7 m. ]) l+ n
void SendResultMessage();- X. [1 T9 ?" v" |$ @
uint16 m_nUDPPort;4 g+ G/ U8 i4 f4 P& n# Q
uint16 m_nTCPPort;- W$ X% i0 y& g. ^5 D- w% e4 ?
uint16 m_nTCPWebPort;8 m2 q6 ]: F( N p% x
bool m_bCheckAndRefresh;3 N: y6 L: b# w4 x
* S/ i# W' A. z( S% [* A/ ]) `# F1 O- d6 X J! c% e
private:
5 `7 W& W: E6 w$ H0 W' n J. n, `0 o HWND m_hResultMessageWindow;6 q/ M7 @# h$ {- x( r, S
UINT m_nResultMessageID;
: S/ E, I9 x, l6 z" x8 _! s1 j( W" N g5 i; f, y$ h- _
0 R0 n c- I+ W0 Y4 W};' c+ t* j( H' X* B, d
' J% i5 ?: x& T5 a6 |- `4 G
' c6 F+ l* h6 D8 c a// Dummy Implementation to be used when no other implementation is available3 [/ M8 Q+ w& c
class CUPnPImplNone: public CUPnPImpl
1 ^! p. F0 O! y' n{
, F! {7 ]7 T* M5 fpublic:
& H* j4 [. J4 D0 K virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }9 H( C; D7 n9 J' h$ Y2 f E
virtual bool CheckAndRefresh() { return false; }# B, j% x) S' W: i/ `
virtual void StopAsyncFind() { }
- f$ w' y: X/ t) m2 y* { virtual void DeletePorts() { }' B6 ?# Y3 S+ i. p! T6 z! }
virtual bool IsReady() { return false; }7 C' Y; {/ m! z0 m) Q: h2 o
virtual int GetImplementationID() { return UPNP_IMPL_NONE; }
* d4 X" N: v, E7 M};
" {1 g# d. V3 `8 S( Y6 O
* h% _& j- m I7 n
' L' T/ G: o1 ?6 K/////////////////////////////////////8 o! M' ~2 ?/ D* F! @3 B
//下面是使用windows操作系统自带的UPNP功能的子类
. ?! W2 ?1 W" B8 L4 z# c) v: |3 A6 |: |; I, Q
7 d5 J6 W; P. d4 }6 z- H
#pragma once
; ^/ `& H% O2 [#pragma warning( disable: 4355 )( z1 b* Z; E& f$ t9 }- H
+ e2 X$ S* }1 s* C+ x
b9 q# P8 y$ A
#include "UPnPImpl.h"
" n, w( `; M2 @3 z9 Q#include <upnp.h>8 l; R( w1 a% Q& m, _; U
#include <iphlpapi.h>2 `8 L+ m. ?6 t, M5 A" Q
#include <comdef.h>1 T) E: k5 s! Y7 f J! h6 r
#include <winsvc.h>
. Y. T2 Z& _- d# B3 G
% R8 h+ r' {9 n, }) P' Z. I' k9 [5 P" v9 T: u% G
#include <vector>7 [+ _8 H4 v# @) ?9 `+ y& {0 d6 b
#include <exception>
7 R4 c) u' ~2 V! p% W' T#include <functional>+ f8 ?0 h; H# \! n. S) B) n
2 c9 X" u7 \: P+ b3 a0 y
$ t( F1 \2 w1 i
. T) y! j1 j% u0 L; G1 }; \; s) g6 G2 c
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;/ f& @% Z7 Z. ?+ s
typedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;" F: i1 W) H+ W8 c& J, J# }) ]* X9 s
typedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;- @: L" m! |2 L3 }9 O& L: u$ Z0 m; [
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;
% f( o* Z( U2 c6 Itypedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;* W; Q4 `2 j. J6 a4 X/ a8 e$ q$ h
typedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;
* w* U* v4 \1 w0 P! ^typedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;( f( A8 `( M$ G
& E- a. q$ z$ U$ D! e8 I
6 h+ z$ ~0 m8 @% etypedef DWORD (WINAPI* TGetBestInterface) (
; T3 t8 A2 |! e) L# r1 E4 N3 P IPAddr dwDestAddr,$ i/ y% J; E0 L1 R
PDWORD pdwBestIfIndex9 Q5 x* r2 h, l8 M& E
);7 C- q/ _, e0 b" A3 [
3 j) K0 ?5 H: m* G6 N
9 r8 j1 \! \: E" {
typedef DWORD (WINAPI* TGetIpAddrTable) (2 f" r) F$ W" h
PMIB_IPADDRTABLE pIpAddrTable,, F8 o6 _# C0 a9 J
PULONG pdwSize,0 o7 w9 b8 g# P
BOOL bOrder
- c" ~* Q! y$ ?);
5 ?) H6 W. f8 S0 @, F( r6 [# z+ h
# w! L0 {- d& I& J# U/ [1 N% q
6 B5 j1 ^- t" o; ^typedef DWORD (WINAPI* TGetIfEntry) (
- B8 U2 L, T$ x: a PMIB_IFROW pIfRow& V2 _' v- |7 J- l1 ~
);
& A) B( c$ Y8 @/ @) j6 }2 q0 F8 v7 t
/ S( C' v% B0 n, h" [2 ^
CString translateUPnPResult(HRESULT hr);
. j' H+ j# T8 v# C! z7 \HRESULT UPnPMessage(HRESULT hr);
; V# ~+ ?; o( B- y3 ?: w
+ E/ w8 D8 B% g' P% M7 H* r7 ]/ B/ e6 b4 D2 h. c
class CUPnPImplWinServ: public CUPnPImpl/ T1 [2 L( u7 b- L t4 e I& q: @
{
& `& a, p7 A. `2 s friend class CDeviceFinderCallback;+ z( K3 G! F# M( P3 i. s; c
friend class CServiceCallback;4 E D. [+ k$ D) `! ]1 z1 M
// Construction
& q# P5 X5 n9 c' b5 Hpublic:
4 l9 Z0 j) H, E9 J9 F virtual ~CUPnPImplWinServ();: s' H8 [8 A4 R' r, Z' K$ m
CUPnPImplWinServ();# l& |$ N# R& F- N" o* x, q
4 F+ i8 r: g) T. A% D& ^* r% |7 p8 ^* b' Y& P" ^& b7 n
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }# s1 Q+ ]- w, l& |$ U
virtual void StopAsyncFind();
$ T/ s: q. j2 ~. w5 Q virtual void DeletePorts();3 |4 j0 B5 c; Y, S9 w. y
virtual bool IsReady();
/ }( t9 A, D8 D+ Y' r, g) k virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }5 b: _ {. P( P/ f1 k
) J H) K/ S- F* \5 O" _
) j$ s, B* n9 X6 z6 N: h
// No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)
+ S" x- e5 S4 i( O! J- x // the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later6 u; V8 O) D9 m) M4 M$ k. y
virtual bool CheckAndRefresh() { return false; };
, O2 ]+ l6 ^' v0 t: m% x& u1 l0 n
+ h, U: T X- S& I2 S& e7 O3 K7 K3 m- ~
protected:
& J/ ?& u6 U! P0 `- I& V3 ?6 A1 U void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);9 G& @! g# _( h' l4 F3 L: g
void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);4 s" I3 ?% B+ {0 P- s ~
void RemoveDevice(CComBSTR bsUDN);
0 X6 ]) N5 s: X bool OnSearchComplete();- Y; p# I& p+ \9 l/ r: \
void Init(); P Y; S/ ~ o1 u8 u& u
/ i" H- z4 [* k0 W9 Q8 y
3 j& p# N7 B: A6 ^ ~$ }8 X
inline bool IsAsyncFindRunning()
. y4 f; b3 m* _ {
( @- O% I% |" Z" B+ v' C& x+ K' E& p if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )3 i; u0 f2 C# R6 `: }# p. q
{. X$ L! ~+ g0 l8 b
m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );
# u* [. _5 n4 H m_bAsyncFindRunning = false;
3 i2 Z( J3 i4 V }4 c. {; x4 I7 z' H1 r
MSG msg;
0 n, `. |; }6 ^ while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
I- ~+ Y1 ?$ o7 t, {6 @ {7 s6 }4 y+ `) t( J
TranslateMessage( &msg );
' I1 a0 S! p& z, W Y5 r* V+ [- p DispatchMessage( &msg );3 L: T+ y. o, b
}
+ X* J/ N n Q! ^: ]" r( | return m_bAsyncFindRunning;
; c1 y6 K& S/ M5 n/ I4 e }' G& ~6 ]/ ]- F3 V4 L
9 {; A% w' ]* m! ^
" C: ?' ^+ P, }. Z3 d TRISTATE m_bUPnPDeviceConnected;
7 q; V/ A* m% H) `( n+ p U
$ l7 o6 ?2 ]/ U+ `4 K) R! h) _& D, w7 m3 F) E, n- f7 q. P
// Implementation
1 h5 Y5 Q7 ]4 H. y5 e9 R // API functions3 t. s0 K0 Q/ Z5 Q: [
SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);
! `1 ^. Q" b( O& [* o! }" B3 L2 k SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);
0 O9 i$ ?/ N* M BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);
% A* K. t u! x1 y BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);
3 J# t2 E4 n# q2 e& W BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);: C% Y6 S6 b& R5 E; ? |
BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);; K4 O7 Q) c2 D; `5 N" q7 `4 B
5 u" u- N6 s. c5 v8 w; |( B+ t
' L$ G7 p# a" j
TGetBestInterface m_pfGetBestInterface;; v! a5 C* q' w: Q
TGetIpAddrTable m_pfGetIpAddrTable;* [: v! O) x7 U- g9 g
TGetIfEntry m_pfGetIfEntry;
, I9 f- a$ D2 c! a/ u( h
: P# o* Y. X0 N( X- x+ b
6 _" N3 N# i" {; d. w static FinderPointer CreateFinderInstance();
/ D5 e" c7 N; F; g( `! S0 A struct FindDevice : std::unary_function< DevicePointer, bool >; P5 g1 K- ~& Q7 H& E: E# F, c
{) @3 \/ R q0 W) e. ~$ A
FindDevice(const CComBSTR& udn) : m_udn( udn ) {}2 @& F, Q3 @6 a8 q# {7 z
result_type operator()(argument_type device) const- C( C) P. |/ l8 u, K
{
$ g0 v4 v' M" }; M: g( ?8 \ CComBSTR deviceName;
% c m3 X3 a" D9 w HRESULT hr = device->get_UniqueDeviceName( &deviceName );
% p' |2 N- b X& B% L
( J) j2 z+ F, L6 z- L
5 y8 q: u( q+ x8 E: O* c2 T if ( FAILED( hr ) ); P n& r/ `+ T% Y6 p1 a
return UPnPMessage( hr ), false;
: S) n6 t" c( ~, j( G9 C; w) B& e) {
" K/ A; c/ c, H# I' T( }& Z3 ?" f9 M7 J5 A, c2 G
return wcscmp( deviceName.m_str, m_udn ) == 0;
( U$ L0 e! M- q/ _( n6 j& f }& E5 S9 l) q9 U1 l1 L
CComBSTR m_udn;+ R- {) L* D& @2 y6 e& F9 j
};
. y2 ?" r3 d/ A2 J, e. \
5 C B4 @ r3 o1 m8 R0 Y! Q void ProcessAsyncFind(CComBSTR bsSearchType);
0 s. |$ R, c/ C# ?! _ HRESULT GetDeviceServices(DevicePointer pDevice);
3 a: {% m5 s. W Q7 D; f% w& ^ void StartPortMapping();8 F/ ? d; s9 L, V' e
HRESULT MapPort(const ServicePointer& service);3 a' n8 v, W! m! ?/ z2 x6 i! i
void DeleteExistingPortMappings(ServicePointer pService);9 o; n+ _( K2 ^! U/ {0 n
void CreatePortMappings(ServicePointer pService);
! K: q) S! p0 ^% r |; J0 b& y HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);4 v' n+ J- y4 Q7 |% q% [2 f2 R9 }" L
HRESULT InvokeAction(ServicePointer pService, CComBSTR action,
1 q$ s" _ {1 E2 z F) L LPCTSTR pszInArgString, CString& strResult);2 u" K/ Q: u r/ a, M$ Z
void StopUPnPService();
# F _* I+ |( Y1 b0 A
, J2 O1 s! i; ~$ J. z$ l' C! ?
2 l) |/ w/ b$ [ // Utility functions+ }9 k4 Y" o5 A1 r; a# B+ r
HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);7 w" T1 x+ I* ?# V( [
INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);
7 |- F& H5 i+ \" [5 J INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);- L* K% L# M+ X: R& ^7 d' ?+ c
void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);
! I6 H7 `0 P# e HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);
: Z7 b4 p% G' H4 X8 ^. R HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);: U& ]4 r/ f3 e4 L. b9 n. w! o! s
CString GetLocalRoutableIP(ServicePointer pService);4 @% {+ H# B7 M$ w
- E) ^# K% U. ?" D" X. i
- q7 D% Q2 C7 V) [// Private members
+ H2 V( N* G) Zprivate:# @; [+ O" [8 m6 S7 K
DWORD m_tLastEvent; // When the last event was received? o) n5 _% j. q3 a9 L8 P
std::vector< DevicePointer > m_pDevices;/ p; c8 o. ]0 \+ m
std::vector< ServicePointer > m_pServices;, d% T& n! K/ h8 D8 x& Q
FinderPointer m_pDeviceFinder;: s) Y2 L. p$ ] G
DeviceFinderCallback m_pDeviceFinderCallback;" ?; H; O0 G' c: i+ N4 I% i& u
ServiceCallback m_pServiceCallback;
' ~& B( H8 u9 ^; M5 @* c+ ]
' L: R+ F! ^. ?" ], _" {" X) d. w) }' O; c- \5 T7 w
LONG m_nAsyncFindHandle;
( ^* e4 j* ]! a* X9 z, ~ bool m_bCOM;6 D8 \* C& b$ d
bool m_bPortIsFree;* j w& ~( Y6 {# `# i ]
CString m_sLocalIP;. J6 a: b& v0 t, x4 v( W) ]
CString m_sExternalIP;. j5 Y1 K! P; e; y
bool m_bADSL; // Is the device ADSL?3 ~0 k# C+ X: F* ~; K+ ^
bool m_ADSLFailed; // Did port mapping failed for the ADSL device?
- G3 B6 c. B& K0 ~0 a" u: C( d0 O- s bool m_bInited;+ S+ M% Z' q: B7 ^$ z
bool m_bAsyncFindRunning;; o2 J1 f0 W% V& ?/ p! B6 X
HMODULE m_hADVAPI32_DLL;# b! O4 H& r$ }) e
HMODULE m_hIPHLPAPI_DLL;+ u3 Y: S* W& u
bool m_bSecondTry;3 c6 }! ?. q: G% ]6 v1 F
bool m_bServiceStartedByEmule;' \9 w1 h. U9 }1 R
bool m_bDisableWANIPSetup;1 M# B1 c# P; y0 E
bool m_bDisableWANPPPSetup; n% p; E1 M: d! N" B7 ~
# |8 u7 A e- g9 U6 }) c0 a8 ?
8 I6 a4 ]/ J! \6 \
};
3 A) C8 ], i7 g; W- L
8 _6 [2 A1 i9 @ q1 y; \+ j: `: P7 c" v# w C( u$ j+ U I2 w
// DeviceFinder Callback' r5 q, V2 r) ?6 o+ n
class CDeviceFinderCallback/ U! k% x5 y. B8 F' E! r; T5 _
: public IUPnPDeviceFinderCallback# v1 Y6 e# I3 }2 I y0 e
{* [* S8 ] R% v I. e
public:
& C+ n( D! A# n e1 {1 L CDeviceFinderCallback(CUPnPImplWinServ& instance)
) l# O& l1 \" M, L : m_instance( instance )
2 L, B" |% a3 p2 m { m_lRefCount = 0; }
6 [, y# X% c7 K: M1 g" _# V
* B- p" t: `+ R* j1 F1 R: D* _. T$ n; T9 X
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);, @0 W! h" Q+ [9 H
STDMETHODIMP_(ULONG) AddRef();
* _. n% p% V$ m/ i/ J* a2 X9 O STDMETHODIMP_(ULONG) Release();- D- @8 h! L8 g$ Z, o
?% R0 w* D. B# o, I
" {; w1 c" B9 K( q" E! z// implementation
# Q. U" Y! g" r5 p3 Yprivate:- E6 O6 m1 E# p
HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);
' i* q: Y" X# ~ HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);
6 B4 z; d6 y% r8 [% |1 {, B HRESULT __stdcall SearchComplete(LONG nFindData);
! O3 s" @( h1 S: h$ x; t4 t) |4 H
; Z" l. H% R/ O/ Y6 e
private:$ w! l% A O. L+ \9 T4 m6 w
CUPnPImplWinServ& m_instance;4 c4 I7 E+ d4 H4 c4 h8 g5 e$ [
LONG m_lRefCount;1 W9 }5 e _# p4 p7 V2 M- C2 H
};; C1 D- b; b4 z+ V5 i
5 ~" X# r+ w1 q% b: i
/ w& f( f! }8 A" F6 G6 V
// Service Callback
3 L% r9 z$ M( G4 k7 I3 B5 Vclass CServiceCallback8 H' h; N0 m& ?
: public IUPnPServiceCallback
7 E- v1 U8 a# j8 a2 o2 z{0 t# O" H9 n2 f4 j. @% r' S
public:
: X, m* B- x$ P1 l, B CServiceCallback(CUPnPImplWinServ& instance)
. u1 p0 K' _+ c8 p : m_instance( instance )
6 R# `( o6 d" y" |/ l0 c { m_lRefCount = 0; }- ]5 J* s) v8 y3 a+ K& r8 E+ I
* \, N0 d+ `3 b/ C' c
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);8 z) k. f7 Z# P
STDMETHODIMP_(ULONG) AddRef(); m& J2 v$ ?" ]' i0 Y
STDMETHODIMP_(ULONG) Release();
; `$ u. y8 q/ A1 o% g X3 E; }" P( l3 u9 a% X
) ]1 [8 m/ B- I
// implementation* \* l8 [% a N9 f8 S' Q% P
private:
. l5 J2 z) n3 i6 i HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);
2 ]- ?1 d5 w, ^) t; C HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);+ ^" n! @0 [! G6 R; p n
" [) Y" s/ x- Q% I7 _8 d4 m- }. x# B/ f+ ~
private:$ K4 j( N1 o4 v- x. n
CUPnPImplWinServ& m_instance;
6 |7 i1 E5 t- b) H6 J' B LONG m_lRefCount;% L0 n$ K8 _. n7 W2 ]- d
};
) G8 n6 Z8 _ o7 g, ^( b
3 ?$ A/ i' w1 [3 | `& o( a4 r& \" ?
9 [8 w1 n9 }4 D( U! j/////////////////////////////////////////////////
: a! l7 m- I: [7 e
* F) X) T2 T! M8 l/ l ?* _5 u& T9 b
$ |4 A, L3 l7 o! t+ S! w5 q使用时只需要使用抽象类的接口。
! [3 n% \4 e+ A+ t' J; vCUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.3 x9 D5 E# j. O7 j. B/ T
CUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口./ K( T# y: {/ \1 I; X" ~
CUPnPImpl::StopAsyncFind停止设备查找.6 ~; }% ~( K! {$ I& v
CUPnPImpl::DeletePorts删除端口映射. |
|