|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule,
5 }6 w- W5 }/ p/ L2 v3 b2 L& u6 _$ Q: Y A
+ Q" C9 H, p( C8 Z///////////////////////////////////////////
/ f. ?+ w5 l, Z+ q% K$ }8 U+ `//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.% W( A; @3 i5 U( r" v9 N. d( Y
) G6 {4 a" n7 ~# ]1 v
7 D7 Z1 C1 {% r#pragma once8 J) m% N+ y3 ~4 h. ~5 R! O/ n
#include <exception>( L2 b6 w% q. F
2 d7 Q$ }2 \+ _% s
/ j! _( _2 w/ n; t' O* @ enum TRISTATE{- B0 x3 @- ~1 I- X' ?
TRIS_FALSE,
; V8 o. [/ N, c. Q7 T" e TRIS_UNKNOWN,* W0 ]- N# g. v5 L5 t& y* Y
TRIS_TRUE
C# R3 w/ w# c1 O1 ]) L& I' G};
0 H& l0 ^; h( w' K# w- t5 { o3 s# a& C4 w: I* e
6 w9 d- T7 L# `# v% q+ c8 Jenum UPNP_IMPLEMENTATION{
( {* S; {! C' d- C' }* L UPNP_IMPL_WINDOWSERVICE = 0,
# Z0 C5 F5 [: t2 j+ j. k$ ^ UPNP_IMPL_MINIUPNPLIB,
/ W. k/ F2 w( h5 _$ z UPNP_IMPL_NONE /*last*/
! l R% @9 g0 K( w/ ?};$ v; r2 o0 [3 j# q
$ P* Y D0 [; e
6 }! i& X6 W5 @- B- b: |
- C: n+ t% f. n, F4 ?' q. T
`! o4 t* `* _7 H# oclass CUPnPImpl
: D, P1 z& {" ]{) W4 x& l! Z( h! p( Z2 P6 M" d( m" W( q
public:; G% w' T9 j% i
CUPnPImpl();
# C6 Z$ B4 G7 z0 @ virtual ~CUPnPImpl();0 X7 A! y; Y7 a7 A' g0 N
struct UPnPError : std::exception {};4 K ?' j C5 l9 l! V
enum {( b2 t' F: v1 S' ?6 [
UPNP_OK,
& [) V1 Q4 v: W1 o" j/ {' r1 a8 I UPNP_FAILED,* ?8 g. a4 B: ^, A& ~/ M
UPNP_TIMEOUT: Y0 B1 d0 i$ O
};
# ^" v5 }0 O! F! }( m: i2 u- D( u* h3 o" i+ G
+ B; {3 |3 F W4 M3 h8 D! D
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;
- T. z- M" C4 v( T6 m) j( q virtual bool CheckAndRefresh() = 0;
- t1 [8 U3 e; U, U J+ a0 ? virtual void StopAsyncFind() = 0;
1 p# _6 v0 K, `+ F% F virtual void DeletePorts() = 0;
$ f4 b# N4 [/ C/ G* S virtual bool IsReady() = 0;! W9 h8 r- y- y% \7 V
virtual int GetImplementationID() = 0;
' M5 R% L0 D4 }" R/ z% w/ ]
, O; O/ S" Q' I) ]2 } void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping
* ~1 D; b. z' Y: T! Q: f/ k
" h6 s3 ~' @4 Q( i9 u5 j( w
; b9 `2 u1 [5 x0 A: z void SetMessageOnResult(HWND hWindow, UINT nMessageID);
! @/ \- z( @% F" n% y6 d* R- H TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }
' s" Y& ~4 t9 Q; L3 F2 N uint16 GetUsedTCPPort() { return m_nTCPPort; }; E+ j1 c" i- p" o# B. _
uint16 GetUsedUDPPort() { return m_nUDPPort; }
( q6 Z- p. b- x4 N$ \ W9 y" D- ?- L
: H( N+ l& F2 D6 S
// Implementation
+ g# R6 k. ^2 b5 Wprotected:
5 p3 }# f) J: T volatile TRISTATE m_bUPnPPortsForwarded;8 i; \8 \' K3 N I% A/ K
void SendResultMessage();
: h* g4 f8 n& r( B5 v" N: j$ A uint16 m_nUDPPort;; G; y# a9 V& K
uint16 m_nTCPPort;# O' U6 C1 C# ]7 y& ~
uint16 m_nTCPWebPort;) s) Z: ]; H2 q8 o# e3 o9 j' b+ r
bool m_bCheckAndRefresh;( @: O( h, O1 Q+ H
4 G( C% o2 A! r4 [/ Y1 n) Y0 j/ _
private:2 l& e/ p8 ?* h) r' D E+ p( f/ `
HWND m_hResultMessageWindow;6 s: M- u# h ]& [: d. p5 P
UINT m_nResultMessageID;# ?/ Z3 ~- x7 r% Q
, ?: ^. {' }8 f* _
, b) ?3 ^5 V; i9 L$ l0 q$ d};" ?* m& z( j; S& W E0 V
! R2 L* `5 Z: Z: T& h7 s
$ s1 o _% d3 U; e9 v// Dummy Implementation to be used when no other implementation is available
4 A" C! b' D% c) ~ Sclass CUPnPImplNone: public CUPnPImpl
. {' Y6 j, ~# }{( n# c# r$ y( u, {$ c y' I( y
public:5 H% z- y3 K& H$ E
virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }
9 N' [) N# M) e2 x+ `9 Q virtual bool CheckAndRefresh() { return false; }1 c, H6 W% g N) [% L0 _
virtual void StopAsyncFind() { }7 A- i3 q- b% I% \2 j; _+ S
virtual void DeletePorts() { }) r# ?8 Y7 w! n
virtual bool IsReady() { return false; }. a. `- N' T# g# {3 o2 a& b
virtual int GetImplementationID() { return UPNP_IMPL_NONE; }- C( A& v- S; Y3 ?8 t! t$ r
};% J3 ^: t% P: G, |9 U4 L) V3 r
, G8 p7 \6 O! u0 ~2 @5 L, @( B- U7 Z
/////////////////////////////////////
8 i- X6 _/ F" V! x& ?//下面是使用windows操作系统自带的UPNP功能的子类# f7 D. j# T. r
" e% e J0 K( h; ? Q( ?$ M
( K( U; w* ?: J0 o#pragma once
3 Z+ Q# D* k$ }4 t* p5 _' k#pragma warning( disable: 4355 )2 N; J' J! u6 }/ Z
c7 j. P% t+ D" o$ v
$ i2 {9 ^* Y! B; c6 L: h3 K: C, A5 e+ P
#include "UPnPImpl.h"
! \& f3 P, n* I' r5 Q#include <upnp.h>
/ O, i4 H4 `: S$ ^# r( ~# ^& n% g b#include <iphlpapi.h>
) R/ |8 g$ `& w/ m3 n#include <comdef.h>
3 C. r6 A6 f2 `% |7 U#include <winsvc.h>, W$ B& o1 E" M1 [7 P
8 |8 X" f/ {7 u' x* v0 x ]) n5 w0 \
$ ^/ H& S* E3 H! b
#include <vector>
! u0 h8 z) P8 N- P1 R0 S& T, ^4 f#include <exception>
4 G! A4 d3 Y, [5 Y2 D% N }#include <functional>0 S3 k; I9 Q) `; j
+ t( m* n# @0 Z: {& U# `* t4 w
# @: a5 o5 ~! I! p
7 t5 x0 \5 z: `7 I( U6 w$ _
6 D' a, B0 L1 N- [typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;, X4 o2 F! O Q% l; y
typedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;: g' W8 b! p# d1 j8 s6 W
typedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;
' \' \" p z# f6 btypedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;0 B( N2 N5 z1 ^# [
typedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;
/ {( i- ?; _# c9 B `4 T" F# \9 {0 htypedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;
; K$ b# a! B/ b" w' O5 w S& Ktypedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;. M3 S& B L. {3 S. Q$ \4 A
% X' |! \* b1 c% e) j$ s% E
1 d2 W/ E& E. B/ x, x6 F. ftypedef DWORD (WINAPI* TGetBestInterface) (
4 K: ]. _' d+ j% s6 ~ IPAddr dwDestAddr,
5 U) y |' k. A* M4 R* V; i( G PDWORD pdwBestIfIndex3 T* j! Y# V7 f* I7 g
);
% D1 }9 D: _ m, |7 o% z
( s- N* w1 J% k8 D) [6 @6 X( X/ F- w8 b; C& `
typedef DWORD (WINAPI* TGetIpAddrTable) (
5 v8 c- I* O9 O/ ^4 v PMIB_IPADDRTABLE pIpAddrTable," H+ E! X) [; D( }* G d( ]
PULONG pdwSize,
% u. v; q9 \0 e0 y' } BOOL bOrder
3 [. l% F/ E# h);# @& i# Q. r* q0 G# e" {
3 H7 w) r. r$ o6 Z G" ]! g2 @3 B; i% J0 E7 O( O2 {2 }5 E
typedef DWORD (WINAPI* TGetIfEntry) (
: Z) P [' D; z" L8 [( L |. o PMIB_IFROW pIfRow6 L4 v/ P* L+ K& D3 s; p
);
. Q1 f3 i4 h" |' S$ k4 K) d% U! L
$ F/ K9 n# j! t+ ]3 @1 d, i5 }% }- m0 k, s
CString translateUPnPResult(HRESULT hr);
% R: n$ O# S2 n7 }HRESULT UPnPMessage(HRESULT hr);8 N: V1 n. r3 H
% H7 I. M& S5 R! ?
7 @& _ C0 J* P8 bclass CUPnPImplWinServ: public CUPnPImpl9 ]" \; i6 X3 o
{! g1 L- A4 R7 D$ h* t
friend class CDeviceFinderCallback;
2 \" `/ S: w$ n8 @5 Q' X friend class CServiceCallback;
4 S' X' H9 h! R5 @) x+ [% D: [( l0 j// Construction
. B; }2 ~6 E/ q" q! K- e% {, M4 spublic:
# |$ U9 Q( r* P9 _* Y4 r. k9 x! { virtual ~CUPnPImplWinServ(); D, E+ N) P* n7 l7 S/ Y/ Y3 U
CUPnPImplWinServ();$ f# V" f- @! k
; z( p7 M/ q5 d' V5 B. l" ~
4 o+ A+ e6 X% _
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }: M# c6 t* E$ p* e! i1 \1 f% A
virtual void StopAsyncFind();: ]7 j" P. b" A$ f% J9 f
virtual void DeletePorts();; p0 a5 p0 ^% ~9 M! `" r( }
virtual bool IsReady();
0 y) ]& V" ^: K virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }. o1 M# d2 e# Z" S! d! m
7 t: v/ F* r3 v, h7 o3 [
* v x g! @! B3 z // No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)
# B- K1 B2 @* K8 U% H% S // the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later( `& ]& l: D& v* z4 U5 L, H
virtual bool CheckAndRefresh() { return false; };
5 o" I1 l% E3 n/ B. T7 Q/ M: F, g! E7 ]5 V( u- \! ]
( ?* h5 N; ?4 Sprotected:
5 u, K2 L! c& `2 A void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry); H u- {9 k8 d2 e8 C. [1 K/ o4 g& g/ o
void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);
$ m9 U! W) u; Q g: d void RemoveDevice(CComBSTR bsUDN);: e: p' p" `2 F- v* o
bool OnSearchComplete();
7 f7 a# P$ l* F# E U void Init();
! {. d; e9 [9 G% Z4 c7 i7 P* l& s- m' R4 f, v k! T
" @. J& j8 \! c& O O0 ]* A
inline bool IsAsyncFindRunning()
u2 V6 x' }* m5 _7 r+ r) B {
2 e6 t/ M0 S$ c if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 ). F" x, s K, o$ J, K
{
. v( o+ i8 E$ V3 M m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle ); O+ T3 \" g* J8 a& S
m_bAsyncFindRunning = false;" |, L6 _9 `4 j6 ?( C) @0 C
}: k. |% z& B3 H2 M3 x/ K! y0 W
MSG msg;9 X( w( d( F/ N @0 l. ~7 u
while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
. f ~) u0 f0 d {
7 H8 A5 L" y0 } TranslateMessage( &msg );
# B R% d/ Z& N9 S5 [' X DispatchMessage( &msg );
* `6 U8 o5 V7 T% i( U }# N. b$ J5 D g) f6 [9 ]! c
return m_bAsyncFindRunning;
4 N# Z$ i a; a$ w( F* o1 Q }/ E: ~$ ~/ z a& v) \+ t# u
. {: f0 m/ ^/ X. N$ F% d. j. u" B. K; u2 Y* ?& F @6 E
TRISTATE m_bUPnPDeviceConnected;" ~8 V2 G5 M; g$ @7 X, ~
8 X' k, X! W2 i
s/ g, C5 B j/ ~, \5 }4 W// Implementation
8 a* i- c$ a% V# s // API functions+ ^+ z: `- p" C+ g
SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);
& h# n- c- M3 ^2 Z: z* o$ s* d SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);
' }/ O% _/ U0 E7 C BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);
+ P, _% g3 D# Z5 y/ z% M BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);5 \/ v7 `! p( s( C. w6 L
BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);
* U# h( Q" H0 a- u+ x BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);
8 ]+ T6 m. @: S8 I& W% N t7 \$ \6 D/ w( r9 M' J! b
* _/ B6 E4 s1 `0 M: ?9 E; Q& |
TGetBestInterface m_pfGetBestInterface; U K \, {0 n+ R' c ~/ z
TGetIpAddrTable m_pfGetIpAddrTable;
* x) V0 |* Z* s) W; h TGetIfEntry m_pfGetIfEntry;
+ K4 h" N3 a5 g. O: ^5 O% }% a0 \7 ]
, s9 L0 D& U# [$ N4 `3 w8 J static FinderPointer CreateFinderInstance();
/ l' E+ ~# B" q% H; { I struct FindDevice : std::unary_function< DevicePointer, bool >7 i$ s8 G% H+ q0 x. h8 I2 Y
{
( S6 T8 z+ c& M. n/ e$ W+ Q' U FindDevice(const CComBSTR& udn) : m_udn( udn ) {}5 w8 l6 ]+ h+ z& X+ J9 h7 g
result_type operator()(argument_type device) const
, V/ w- s% V( } Y; \ B1 v9 D4 C" R! M {
# h, m) {( R. B+ r CComBSTR deviceName;' w9 `* o( A: X! X: A* x0 I
HRESULT hr = device->get_UniqueDeviceName( &deviceName );
& N5 a0 f6 P$ Y2 H! p" J, |, l [& l" D- N" ?5 k
/ ^1 G; r( q i% J) G* ?& v; l# Y
if ( FAILED( hr ) )
) R6 \5 h: z% l5 J1 S: i; s return UPnPMessage( hr ), false;4 h( ?. K F7 B: n+ L5 ~. D
/ C! }+ V7 b0 l& G# o+ b% \: x c8 b* z- V- T
return wcscmp( deviceName.m_str, m_udn ) == 0;3 @1 f' J# Z) y/ d" p0 T6 J& R
}( g" ~* L8 t' W4 m4 Y
CComBSTR m_udn;: t0 T5 G3 p8 D& ]. k% s7 g
};
" V& f( x) H @ {0 @, u ' C8 S5 S$ D4 z6 i3 G3 n" X' O( |
void ProcessAsyncFind(CComBSTR bsSearchType);
# u4 o) ~7 H& R1 i: r2 z! ~, Y t HRESULT GetDeviceServices(DevicePointer pDevice);" F' v {; q$ q% n( T
void StartPortMapping();0 k y0 b1 ?# n5 E# j4 u5 X
HRESULT MapPort(const ServicePointer& service);9 I R% k3 B& h, y
void DeleteExistingPortMappings(ServicePointer pService);; x4 [9 f& ?; S/ Q. Y$ e
void CreatePortMappings(ServicePointer pService);8 T* Q9 C3 L; j+ J7 G8 f/ l+ B- B
HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);; ^5 q# o3 b: R- t- p# h% e5 _$ x: @
HRESULT InvokeAction(ServicePointer pService, CComBSTR action,
$ P# U% ~0 h0 G5 E LPCTSTR pszInArgString, CString& strResult);& @" s0 i9 H2 t; N
void StopUPnPService();
0 D6 g: k! U) G8 K4 x) Y5 H* K0 f) ]. H6 G* R% f
K: Z3 U0 n2 q4 Y# T- y2 U6 ]& [
// Utility functions; w9 @7 w7 k4 ~# {$ W& d
HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);
6 r2 K) x# D; q" i, n" h! b, K K" ~ INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);2 i3 Y; P9 D: q4 I
INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);% g) O4 \' U* i
void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);
p6 B9 z# O k2 p) ` HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);
2 r0 `& y F/ S7 [0 L HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);: n- K8 C( w4 | a
CString GetLocalRoutableIP(ServicePointer pService);
! V7 w- |: Q0 f
* q, I0 N* z' V3 n' j$ D7 c: j6 X1 A3 x; Q
// Private members
" w& y: J8 z+ @8 M+ T; f: Zprivate:
) n) ]' M. _4 H DWORD m_tLastEvent; // When the last event was received?: ~5 u5 [; W0 \! }& Y
std::vector< DevicePointer > m_pDevices;" z8 Y( }% R4 Y$ e% c5 `0 B6 _
std::vector< ServicePointer > m_pServices;. O* m) \, D1 j* }/ r- t
FinderPointer m_pDeviceFinder;4 H/ |/ {9 g1 t* ^4 Y
DeviceFinderCallback m_pDeviceFinderCallback;( y& i+ s, o& x5 L. e4 b0 P
ServiceCallback m_pServiceCallback;
9 L6 c; J: @# T- ~! H( ?) m
4 G/ I* q7 V d: y# @- u3 g) t4 U; ]* `: r1 O
LONG m_nAsyncFindHandle;
+ Y& H% C% X7 ?! A' o bool m_bCOM;5 J6 B, O7 Q! V {+ k0 G
bool m_bPortIsFree;2 F& V4 ]) Z8 x" c
CString m_sLocalIP;
# `! I2 S* n0 z* B CString m_sExternalIP;3 W4 i/ ?$ _6 f8 u% v$ f
bool m_bADSL; // Is the device ADSL?/ \& e) t( K2 ?+ S# e( \: ^& C
bool m_ADSLFailed; // Did port mapping failed for the ADSL device?
+ t7 D. B! h9 E bool m_bInited;& z6 q" m9 `) @& f4 _0 @, }
bool m_bAsyncFindRunning;# i/ k" n8 W+ X- e( D
HMODULE m_hADVAPI32_DLL;6 N) ^! {1 \) D @) z
HMODULE m_hIPHLPAPI_DLL;: l d- V' O7 r" ~+ h8 m7 B
bool m_bSecondTry;; B0 s; v/ d7 w( J1 k- Q. {- U! A* s
bool m_bServiceStartedByEmule;
; u3 x- \% K0 W" j5 G8 t bool m_bDisableWANIPSetup;
8 D" c# Y3 L2 C, v6 X7 `" n bool m_bDisableWANPPPSetup;, x4 U" y C- |; |
+ L) G6 K) ~7 H9 S
" u* R+ H3 k5 A3 J};) H4 U! B$ I9 k; f! ^6 Z2 H
! h _$ F9 y- z3 y/ e8 b' C# M7 R
- m7 M# t6 q8 R7 c, A6 A8 P9 t _// DeviceFinder Callback
9 K4 Y8 D" T! t) F m; Tclass CDeviceFinderCallback
! [* h/ e* a. ? : public IUPnPDeviceFinderCallback
5 }0 Z0 F* ~3 g" q* R7 w) h{% X+ i$ }, s F
public:
" P9 b. Q/ Q* `) V# ]8 Q- O1 a CDeviceFinderCallback(CUPnPImplWinServ& instance); a& c" k. g* G: z5 \8 p4 M
: m_instance( instance )% t, C# t3 @* A- h1 A6 @
{ m_lRefCount = 0; }& `# d/ ^4 I2 n" D) ?
+ S: d3 ]7 Q$ p# f% L0 b# q; n
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
" x; ?7 o& m) o c- { STDMETHODIMP_(ULONG) AddRef();- u) ?. H! I: `0 V
STDMETHODIMP_(ULONG) Release();
4 l) [5 N9 e8 W0 X6 t( q, M1 [ I' ]' T5 M( l
/ }: J0 c2 p1 o3 o& {, e# v1 q' o
// implementation5 J$ k: h- J9 z& L8 s
private:
& A9 l1 c* [& u- V1 b HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);1 k1 M" U4 B. l8 u
HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);8 |' G" Y+ z+ T, T5 S& l
HRESULT __stdcall SearchComplete(LONG nFindData);
/ [0 @) S6 C% J5 g) n+ K9 W1 U+ \! U
; w* e0 Q: O8 X5 ]3 A) r% Oprivate:+ e( G' w9 u; E+ c
CUPnPImplWinServ& m_instance;. \6 R$ F. Q8 u( D; T
LONG m_lRefCount;9 G* j0 B ^0 H. v3 V$ Q9 J, @1 {
};
6 X g B0 z0 Q8 ^; x. d7 [9 p- p' W% M
/ z8 W1 h/ G W& b B* }) [// Service Callback 7 l% K t4 C. H5 Q0 N
class CServiceCallback
8 v) @$ }) l h: x6 Y6 C- e9 i! V7 \ : public IUPnPServiceCallback
1 N) M; K5 K$ ~. F! E{
* Q H: E9 ], X7 o( a5 @public:( a3 C. B8 r. B6 B
CServiceCallback(CUPnPImplWinServ& instance)7 R" H( P" [7 J* K- |6 \# {- q
: m_instance( instance )9 g' A* t+ E" R- k9 J% s! q
{ m_lRefCount = 0; }
1 W/ l) ^9 }$ B8 o9 ~5 K
# N; U. O% u1 u7 T: N! c2 Z STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
/ P e6 C" S, q: @" x$ c STDMETHODIMP_(ULONG) AddRef();) J e7 O, n8 H, k _( V
STDMETHODIMP_(ULONG) Release();
: }7 P; O2 _2 ~! c4 d# `% {: V% ]1 q8 B
) [1 f2 d% Y' Q/ u) V- {
// implementation
) X: ^- M8 [2 F0 E$ p4 C0 M& S' x# Sprivate:7 K( }9 ^0 }# y$ V) i1 e
HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);
) K$ ~, N$ P4 V8 T( j: E' B HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);: d1 Z" S* s$ Q; W. z
. b) I+ b* d5 k* B4 {- K
# V) r: f, M( g3 ^private:9 H3 i0 l6 p# {2 d" z, Y
CUPnPImplWinServ& m_instance;
8 B& a- A. M$ y3 ?; e& J/ p9 r" { LONG m_lRefCount;
% ]* N2 k' @# |2 E4 K& ~$ C; E! D};: q5 j; r7 p7 x" o
8 u8 f( y2 _6 |6 r0 w- b
8 J9 e7 P) Y+ N$ R& h& G/////////////////////////////////////////////////
5 m9 Z6 c; ~& K' E4 K) y& S9 h( {5 v, O8 r# m" A: d" H6 P$ N
$ h" w+ f/ F5 g: i4 M8 z0 ` A
使用时只需要使用抽象类的接口。
* j) h* n* L3 w' h; b9 @, @' BCUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.5 F; R2 K2 h5 Z) I
CUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.
# y! w: X7 m* w6 o6 t& R- x3 U$ |CUPnPImpl::StopAsyncFind停止设备查找.
" V: w2 B' y* z6 S0 W+ m' fCUPnPImpl::DeletePorts删除端口映射. |
|