|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule," m% d7 A* G7 x, s% J
. f. o$ L1 Q" N5 I
2 c( c1 D$ D! k, C7 ?
///////////////////////////////////////////
% L; |. G6 G/ a U+ |8 z G; X- p//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.: `+ H- s# g+ o
. q( @9 S q$ ^3 _
7 A- h# w- f# V# m. v! @
#pragma once
! y/ u0 V$ j7 ]1 i+ F. b& C" d#include <exception>$ Y; [& o; q6 M7 {
+ B" m! l9 \# G( N8 L
1 {% I1 d5 D& A9 \) W5 \ enum TRISTATE{: C/ Y4 ^2 A8 G. c; C
TRIS_FALSE,
6 x8 J( [' F! x TRIS_UNKNOWN,( h- @' v5 v; c( g8 Z K3 P& @
TRIS_TRUE' [- ?& ~5 v$ c( h
};; m' W1 m, n$ ?
! ?9 a. ]. V3 G! F6 Y" H2 l) e
$ X8 d ]) S& g1 h) {+ nenum UPNP_IMPLEMENTATION{
5 k* G* U$ r/ F0 C R% i2 Z& _ UPNP_IMPL_WINDOWSERVICE = 0,6 y o% O7 ]8 J
UPNP_IMPL_MINIUPNPLIB,: K! l2 ~5 T8 m5 W. _
UPNP_IMPL_NONE /*last*/
' W) I& o; C0 G) E) I};1 ? U2 {; u# w. b1 {7 y! A7 Y
( {% ~0 j; c. ?' p8 ~3 |! A( n) F* k
$ ^7 x" e( Q! ^5 o7 \! @% d
. |, M% F+ e* [% i5 j$ Z# x/ h2 o) b4 Z9 E9 T- r0 w. J$ S, ^- ?
class CUPnPImpl
z5 l( a- @+ u" G1 J{
" h0 D0 Z: s- v2 e$ {public:! y( l8 X' m4 G, Q; ^/ L2 x
CUPnPImpl(); F. |0 C# n2 A! \( j
virtual ~CUPnPImpl();" j. y2 D' d; `9 i, l( t
struct UPnPError : std::exception {};
: U2 V- T4 \1 j# ` enum {
/ e) `* l0 K4 d7 b3 `( I UPNP_OK,
: P! Q. t G/ o# p9 c2 T p! b UPNP_FAILED,
4 z! V& _# ?% g5 @7 T P UPNP_TIMEOUT
' w" y1 v$ S9 M# C6 J2 E };
& L' D* v9 d3 e* T
- Y( J7 _; d; l- h
: r8 Z# a; Y# t2 C' ~ virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;) D$ z) w% A+ D8 {; s) T
virtual bool CheckAndRefresh() = 0;
8 b/ ]+ T" x3 s; A# y virtual void StopAsyncFind() = 0;4 m8 v+ N; ]4 ~+ Z
virtual void DeletePorts() = 0;9 k0 f: T) l3 J
virtual bool IsReady() = 0;
* _9 o5 ]" I$ f, b" k virtual int GetImplementationID() = 0;
+ L6 {4 K! ^/ {% p ! M% A( E% F9 x0 u4 h( }( J
void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping7 m4 w& ^- F/ x8 K; d2 F: m
0 c% X, l6 e2 Z& Z" z5 ^
1 R1 V# |- V+ W: z void SetMessageOnResult(HWND hWindow, UINT nMessageID);
9 g& a; E0 b4 W6 S TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }
$ G0 [) {6 ~3 E. l* ? uint16 GetUsedTCPPort() { return m_nTCPPort; }" B+ v# X5 W. g
uint16 GetUsedUDPPort() { return m_nUDPPort; }
5 y% H- A2 ~1 j$ O- \: K2 X+ {. d' {/ `& G, {
" E7 Y" s" n8 w% ?- q
// Implementation
- Y& d- G( e7 f- bprotected:$ V2 V( }& h4 J& x7 D
volatile TRISTATE m_bUPnPPortsForwarded;
% X7 C6 y7 f$ Y* O void SendResultMessage();
2 K" N2 i+ o% N* h; C ` uint16 m_nUDPPort;& w# P& M/ J( v2 y5 f
uint16 m_nTCPPort;
8 n$ ~, n# g1 `- V7 G, _0 T0 p8 r uint16 m_nTCPWebPort;
+ T- _' ]4 x! m. o n bool m_bCheckAndRefresh;/ i! O- j0 t) c1 I, ?
# l. a% A* U A4 G
# G6 Q' g0 p9 u9 L! Z- gprivate:) _( V/ w! v& x. x+ \
HWND m_hResultMessageWindow;5 X6 A! F/ E7 d# v$ ?! C5 ~/ b
UINT m_nResultMessageID;* t$ d0 e3 E N- D; ~9 q
$ }2 T$ `6 A2 Q
8 [- p$ d. Y( j/ _3 J8 a5 b+ z2 A, P};
" c3 v; O% j$ N# j% \* J" i( t4 | ?4 X- H& x, s: X5 v
- h- M3 P& ]0 I$ \// Dummy Implementation to be used when no other implementation is available( h: p6 m+ z2 f2 M/ U+ v) t
class CUPnPImplNone: public CUPnPImpl2 K9 E8 F$ G+ N) c0 M* n
{
% |: T" r8 }% Mpublic:
/ u6 {6 p% r. N8 P$ t' ~: y- U virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }, P# C0 a3 H9 m2 R9 h* s
virtual bool CheckAndRefresh() { return false; }7 h- ?) ]! R2 U' U# e
virtual void StopAsyncFind() { }% Z, |5 x: |, I9 O/ U& r
virtual void DeletePorts() { }
: b( ? n1 G& R" Z virtual bool IsReady() { return false; }
& _8 a$ n# Z0 [0 N9 r! k, t4 M virtual int GetImplementationID() { return UPNP_IMPL_NONE; }' W9 O6 m. K- m# c
};
% o# p* F3 Q, F! \, Z F
& Z- J- z* G; l% p8 i5 D' U: ]- f; `, O* q( E8 u" b( Z2 o
/////////////////////////////////////
; P* o1 s/ j) d1 {3 x: k& K! r//下面是使用windows操作系统自带的UPNP功能的子类
. T2 }3 s1 U* x9 D' y& s# l& b1 P+ f5 ~. k0 ]7 ?
+ b L k8 u ?1 |# o8 [
#pragma once9 R& d4 K9 e4 q( P+ O1 l7 g' k
#pragma warning( disable: 4355 )
% K X2 |: @. F4 ?8 k! n- P7 {& n! X8 a) U7 s$ d0 U. V
) y! U( a, a( ?% m#include "UPnPImpl.h"
& ?$ t/ R6 M# c. n$ [! Y#include <upnp.h>
9 c- A1 g5 W* o$ ~ O h#include <iphlpapi.h>
n4 G$ Q* }/ n& ?+ }/ W#include <comdef.h>! h( W1 W; i: {% @* P! |# M/ ]6 O! g
#include <winsvc.h>
$ \9 a+ S( d2 N# J0 i
$ Y6 O5 m9 e0 f' o; n7 q- b" G! y7 A4 f7 P) X# h8 K6 k% a
#include <vector>
- Y+ K' S% @5 c4 T( j% v# ~#include <exception>6 w; N& ~2 X% @2 q. p
#include <functional>$ |7 w* |! u7 `% y
, q3 m. x& n Z
* w' S, C( p. b% R8 x- c
0 y' V" x) Q7 h! [ }* M% @" p) w J- H1 d
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;. f2 C7 ~# ?/ [9 j, a
typedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;3 S% V+ O8 M: U) @/ q
typedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;5 `% L8 ?* A) m0 X' b
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;9 u5 Z, Z r9 V; [( _
typedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;5 p p4 Q2 b5 d8 W: g/ q# _- \
typedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;
) V7 @4 E$ w& L* p% \typedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;" e% o. w( w* ~/ U& }8 i' `1 b
: [3 n# A2 ?% Q: t* h% U
% H5 d% O) F& `5 J* \typedef DWORD (WINAPI* TGetBestInterface) (
9 f' W, s! p% ]3 [! v0 X IPAddr dwDestAddr,3 m) t! A& S2 v
PDWORD pdwBestIfIndex
! I5 R# v4 W6 b# h5 F: e) Y$ H# B. j);' n2 g2 @/ g$ G+ N% ?* }9 H+ D
& b4 X6 ?9 E' o: E2 l. X5 x
; O/ @, Q, m$ s
typedef DWORD (WINAPI* TGetIpAddrTable) (
8 \ B: B. y B' a( Z8 a: r PMIB_IPADDRTABLE pIpAddrTable,
6 S% u- B/ }7 x PULONG pdwSize,
# Q: g0 |* o [! G# H2 J BOOL bOrder9 y+ u0 n5 _: A, @% t& n7 Z
);, h% @# O( e W$ D/ R# D
; z% T9 I6 e" S' x2 ~( i
# y* H; c" G8 d
typedef DWORD (WINAPI* TGetIfEntry) (
( C) \& d% M* a: R! O6 B PMIB_IFROW pIfRow
8 I* r1 G) X- n* J1 ]);
' L3 E1 a, s6 ^. W- b
2 S% P" x, \) `/ S5 h4 {( e
/ i9 |8 w" e6 ] m+ B3 eCString translateUPnPResult(HRESULT hr);
/ s. X8 [! E( l( m& H4 tHRESULT UPnPMessage(HRESULT hr);' o% N" ]( {) ^& e
; {. E, `0 J# {+ b+ I4 V* ^
+ g: i8 K& M- o" S: N( `
class CUPnPImplWinServ: public CUPnPImpl
6 V4 `0 _! V2 t( I" T{
6 O% R5 ]$ R4 k/ @1 j friend class CDeviceFinderCallback;0 |% P* K8 w2 h$ O! E9 V
friend class CServiceCallback;$ ^2 t# D$ i- `
// Construction
/ ?1 L) y& E8 @# v7 [+ W. S$ tpublic:; y- v, q M# P- t4 U b. m( t9 ]1 L4 ?) Z
virtual ~CUPnPImplWinServ();- Z2 u# ]( |" N0 ?" r( q
CUPnPImplWinServ();
5 b0 I& v% Z- M- n$ N, t# j n7 w
3 ^) A6 n& Y( d/ _
* f9 v1 [. m+ \ virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }$ D# z$ O' B G5 B$ h
virtual void StopAsyncFind();
7 ` H8 n; \. r% J9 k# S virtual void DeletePorts();
& G, f% e. X6 i F; x virtual bool IsReady();7 O. t+ v* F* I: V' P8 s! ^
virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }/ u+ h$ h, q s q
. e# r4 y* T1 F7 {+ Z7 d- t9 |
: `6 m& F" m( _+ w% a5 ?! ]$ f // No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)
* \6 X% r8 A3 f* ^ // the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later
: A% u: c ^- _8 d7 ~ virtual bool CheckAndRefresh() { return false; };
- V# o) O+ V$ P- ]/ K3 K9 G/ @% Q' r! }5 \8 o3 `4 m6 m' a1 U
! s" n8 {: a9 z4 b$ R
protected:
: W% f( E- R1 ?. }1 B+ e ~0 a void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);# h ?! }4 H4 q0 n$ h; D
void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);
0 c9 n" c/ D4 y: r% A void RemoveDevice(CComBSTR bsUDN);
8 [* \) Z! `! M& } bool OnSearchComplete();0 {- I! D9 S6 M) e/ M& K% a
void Init();
0 T0 t# s: C$ U& F" z& P( s. b1 a6 q) @' Q& d
! F* M- Y& B) t" h. E) b/ P/ m2 y
inline bool IsAsyncFindRunning() . J& q) t$ g: Z. R
{
* Z$ m$ K; D6 _% j' h if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )
2 N& k. P) _2 q) _) v0 B' I+ k {0 n2 M' k; K% o/ B; Q
m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );
) ^( _7 g- ]5 R; s. X m_bAsyncFindRunning = false;
4 w# s! j; ]- x& U# a' V5 d. |4 @ }1 P" j, f& m! N5 u9 D
MSG msg;
3 a, } [" v! V. ^4 ~3 { while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )+ G* u! b$ y7 E- c! i
{8 V8 b& t) W& U
TranslateMessage( &msg );
5 M! X( S% v" V0 t2 y DispatchMessage( &msg );
( X' S8 Z9 ?/ L. U) h }# C5 o0 [2 w, r8 ^5 n
return m_bAsyncFindRunning;
' L0 n- A+ j ^6 ^% c" d }, r; L; Q# t4 p$ ~ U
* |! [( R6 S1 \6 r6 m, L" K" l. g* h* S* C0 W
TRISTATE m_bUPnPDeviceConnected;6 m" Y5 D! v& W/ _- y
7 r0 y; Y I3 y* S( t" V# z
; k- K, W0 ^7 o, x' f// Implementation; Z* \9 u" u; W' H7 m
// API functions9 f6 s* S% \8 ?& M$ `* d" ^$ N
SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);
+ z% U, _8 k f SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);
2 C2 ~) n" K( f BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD); Q @# N- S4 D9 N+ P5 h4 X
BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);" ~2 o3 H" a& `8 m! C' y( y) a
BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);( c) ?: S* X" u* v- L
BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);
+ w: _: v+ ~) ]1 ~! j
4 j1 R1 C+ Y$ [6 u+ |$ g
9 `) m b- F. E+ s$ z9 E TGetBestInterface m_pfGetBestInterface;9 \2 ?. h! j0 C, j5 ], X% N4 v
TGetIpAddrTable m_pfGetIpAddrTable;/ B5 d! J4 i* n( P2 T% w* N. n
TGetIfEntry m_pfGetIfEntry;: S& I+ [: b, L" C) h
- m* U/ Y% u2 ~ q8 O! g! S
. b( R- P. `! e. } F6 o static FinderPointer CreateFinderInstance();$ N7 Q- a+ K/ Y8 \7 w! w) t; l/ p) |
struct FindDevice : std::unary_function< DevicePointer, bool >0 C5 l. u( I1 p% e
{% v0 v' y( m+ u' D0 q- h
FindDevice(const CComBSTR& udn) : m_udn( udn ) {}% s9 M. U) Y/ t5 j& y( j/ K
result_type operator()(argument_type device) const
" `- v$ n7 ?! K" U% x% e# ~' B {
c$ L. V! ]% f2 t, i1 v- ^ CComBSTR deviceName;/ a+ ^- Z: N. E
HRESULT hr = device->get_UniqueDeviceName( &deviceName );! o/ y/ F2 ~9 x% X; E
" T$ V7 k9 S7 ?3 u; y
& ]4 B7 G% b- q6 y, @3 W, e if ( FAILED( hr ) )5 u$ L+ q0 |+ s3 ~* v7 r) ]5 E
return UPnPMessage( hr ), false;
' T) v9 a( r0 ?2 f4 I% B/ i/ i8 S' W" `% v
7 w0 r0 |( j) L/ G5 ]: g3 _
return wcscmp( deviceName.m_str, m_udn ) == 0;) k: `3 N" t; i& O+ o
}
) ^ H& K0 ^4 N9 r# S CComBSTR m_udn;' R) S# t- G/ _; M+ i
};% t) g% r$ d& j8 I. w0 `3 r) I
4 x* K- [. U7 G2 X# [. D5 E
void ProcessAsyncFind(CComBSTR bsSearchType);
, E# Y6 R+ N" h! f; n% B h HRESULT GetDeviceServices(DevicePointer pDevice);0 }9 w. a% i9 N3 c5 o2 X% V5 ^
void StartPortMapping();
& g$ J7 z) a- a HRESULT MapPort(const ServicePointer& service);4 M0 y; K/ F. q; d0 _3 y4 S% R
void DeleteExistingPortMappings(ServicePointer pService);
+ J* C" E, {' @& ? void CreatePortMappings(ServicePointer pService);
5 s) `% H% j! W3 Z HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);5 a& |. L( c$ D2 O' V
HRESULT InvokeAction(ServicePointer pService, CComBSTR action,
$ `; y1 N; }, u& \ LPCTSTR pszInArgString, CString& strResult);/ {2 N. L G& o1 B' w; f
void StopUPnPService();
& x# Y4 m; B8 S' Z% I: }1 Y5 w4 d' |% x" z/ X2 @/ |3 c' K
) b- P8 }/ z' k
// Utility functions6 g, O' |7 B& ~7 P
HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);
& D! x, t" L1 R9 a @$ J) d+ d INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);+ o9 g/ ^" o( X5 m1 F
INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);
8 x. [% L; \; ^' o r Z3 r void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);: S6 W) {2 j. o& L# x0 h1 c
HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);" l! V4 u; `7 Z' i/ Y
HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);* e# v: P3 o; [: J
CString GetLocalRoutableIP(ServicePointer pService);. O8 o1 m* T* W/ v
9 Y( D1 T4 b4 V1 v
" y4 v/ U1 N5 R0 P2 X1 V/ u& O$ m
// Private members( _) z/ X! v0 P! u( {
private:
6 N! g7 P+ H$ Q' b9 [ DWORD m_tLastEvent; // When the last event was received?
( ~! i0 k1 i+ B- {0 w& c! s std::vector< DevicePointer > m_pDevices;+ l$ n# A. ]% u- e3 Q. I) t W
std::vector< ServicePointer > m_pServices;, }( T# o; A0 _3 D6 z) t& s
FinderPointer m_pDeviceFinder;3 }9 D( S- k: y: Z. H
DeviceFinderCallback m_pDeviceFinderCallback;6 q- A& ]! w: w* _- l6 c. {8 d: o
ServiceCallback m_pServiceCallback;7 W2 a9 q% |" B9 k
% \4 H, U% @, m _. R: L
) J% _9 S7 c8 O, ^ LONG m_nAsyncFindHandle;) C- A: H* Y8 V$ l, g7 C
bool m_bCOM;
+ j' j* c+ e2 _# N4 m bool m_bPortIsFree;8 t0 x* a3 I) ]# N0 q
CString m_sLocalIP;0 ]) Z- o2 y) u8 }( L7 G/ n
CString m_sExternalIP; [6 ^) e6 j9 Z/ I+ [
bool m_bADSL; // Is the device ADSL?
( x: _ D+ @" Z! r! z! Y, ^8 E bool m_ADSLFailed; // Did port mapping failed for the ADSL device?" v8 q' u( J4 A1 t
bool m_bInited;2 s/ s- H* g) h! H4 a
bool m_bAsyncFindRunning;
. l4 c" _1 `3 v+ q! W9 h HMODULE m_hADVAPI32_DLL;
% [/ j6 o2 y1 F+ G9 K7 v% W HMODULE m_hIPHLPAPI_DLL;
6 r% u2 {/ i# \9 { bool m_bSecondTry;
2 S! e1 T* Y* ~$ h p2 \8 v bool m_bServiceStartedByEmule;
% C' C! b% a# k bool m_bDisableWANIPSetup;
5 \ ^3 `9 d# q! b$ { D9 O bool m_bDisableWANPPPSetup;. E! X$ \. ?' O9 Q
: C& E: | K2 W; B6 x" H6 W
# a$ q: t5 Z6 ?5 D- r. I2 M};! I. B+ t/ M1 z- }. u) D2 T
; \+ s8 I T+ z, I
$ }, y7 q6 o2 o3 U6 B& f- o0 U, P// DeviceFinder Callback' O7 T7 K) C$ q. O, _) ?' f
class CDeviceFinderCallback3 V3 P; F0 C: |3 S3 _
: public IUPnPDeviceFinderCallback x1 W/ ?" d) @ A
{
0 C+ n- s" ^8 j* S! O; k9 spublic:: O8 A% I4 ~. F+ v$ @. u
CDeviceFinderCallback(CUPnPImplWinServ& instance)
/ o! g& Y6 B9 B0 I : m_instance( instance )
! _4 x# q7 @; Q$ I/ t# G8 o { m_lRefCount = 0; }
- ]( O: J7 k) J5 P' n D
: m' t$ b. c( X% j
4 O9 M! |- Z& a |" N- o STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);: N; C5 J/ r3 g+ q
STDMETHODIMP_(ULONG) AddRef();
l# X* v: f) r$ _, V, t2 z STDMETHODIMP_(ULONG) Release();
; G( w) O8 G5 I' M2 l! m! q; w2 t. s* E4 c( Y
) I. ?* N3 y0 _& i' W
// implementation/ _6 O$ h6 f/ Z: y1 u( @
private:9 F6 t, X8 R5 U$ c" s
HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);' u/ A: x/ n& @5 k0 E
HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);
% V9 Y: K0 X1 i: {4 u1 I: G HRESULT __stdcall SearchComplete(LONG nFindData);2 g2 T6 ]( q3 [( {& T
4 d% Q# O: Q# N- E; h( i& M
1 W, u3 H" e2 \, U! lprivate:3 ~- v- ]# ~2 X: R9 W; r7 O# o
CUPnPImplWinServ& m_instance;
" T* ~$ n; A+ n+ [2 B8 c) L LONG m_lRefCount;
0 I) O7 e: A. X# f8 S};7 n' b7 y' u9 s7 {: L. R
1 d9 x" A) F$ Z# I5 g, U4 A
# d, n+ Z S) A, s// Service Callback # _. b1 A7 T y% b
class CServiceCallback
% S" Z# T# ]& w: o" T : public IUPnPServiceCallback
% K1 w2 a$ H4 n{
- e, J* i& ?2 ], k3 [8 a! O2 m& ppublic:
5 F' N# @* o" X5 G! h CServiceCallback(CUPnPImplWinServ& instance)) f; Q+ b! I) q; a
: m_instance( instance ), u' j% z- I# Q6 V- y* ?
{ m_lRefCount = 0; }
+ ^1 `" i* h; s% \, f( R" k' o 1 H. X2 L' t+ h1 e1 x# t8 x$ ?
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
$ [2 r* @$ S" ]% Y STDMETHODIMP_(ULONG) AddRef();4 I' [; X0 x& ^' s8 v5 @" S
STDMETHODIMP_(ULONG) Release();
( D* j4 B1 ?4 A" h1 m- k7 M4 q0 E' ]5 p4 w5 s0 P8 c3 z
I5 Y W1 d0 P) g1 X) k// implementation6 g1 C) ~9 ^$ a& x! u
private:7 A" L! n2 E2 _) n1 f
HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);4 i% t, g/ { V4 E( L# ^. r
HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);
( _3 m3 G4 S4 Q4 k
! {( Y, @7 ^) ?0 k
) d$ ?( h) K$ d, U3 ?* e; xprivate:" x6 }( X2 {2 h5 \
CUPnPImplWinServ& m_instance;
o# @+ O1 F+ m/ p n LONG m_lRefCount;6 u$ b: w- a2 B
};2 n8 m) J: k4 E0 Z" w% {
7 q1 l N) \) c1 d+ A
. Z, v& @9 T% t+ ^: X
/////////////////////////////////////////////////$ N! ^& U& \! M" [2 _- s
8 w! p5 ~. i# U7 r) E q: }
5 X# \: a: ~; h! D, s) W, s8 c0 l, J
使用时只需要使用抽象类的接口。
8 w& i! p4 |; \8 Q1 S1 W! m7 Z+ A: `CUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.
3 G2 }) b& H4 x% s. _* ~CUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口. H; |/ o9 _/ L
CUPnPImpl::StopAsyncFind停止设备查找.8 A, h6 z0 _, ` u. o0 O
CUPnPImpl::DeletePorts删除端口映射. |
|