|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule," ?0 R4 v+ o% T @; }- E1 U
& f: ]2 g+ k' I+ h1 o( g
, f2 Y$ c" K/ I' y' }7 M///////////////////////////////////////////" [( \- I s" |/ d- a; `% _
//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.3 C X! b J$ M* H0 n) C
. C* g. B3 j) g+ c# @. _) F+ Y0 ^- U4 z
#pragma once* L2 C: |, b Z, c& d/ }% ~
#include <exception>( u4 H9 I0 v, c& l( ]1 {" N
/ \* A# E# y: E& C7 ?4 S) B1 U+ p4 r x$ N/ u( A) t4 L. n8 I; T) k
enum TRISTATE{
2 \# G' o. W- I8 T' a: V TRIS_FALSE,2 q) O- V B/ s, a5 L* V9 o
TRIS_UNKNOWN,
5 [4 h1 \! M8 O, p; X TRIS_TRUE
* r0 R9 v( E, ^' W; @" _};
( a Q* j5 ? }. x H0 o8 U5 D7 i: c0 q! o( u
# Z! H* X/ C: O/ e8 ~% W" p4 V: O
enum UPNP_IMPLEMENTATION{- |& U2 ^+ A* w! H0 _8 {; f
UPNP_IMPL_WINDOWSERVICE = 0,
6 ?- S) L6 t, h UPNP_IMPL_MINIUPNPLIB,
0 l+ M: G3 ] X UPNP_IMPL_NONE /*last*/
?9 ?6 q* O J: _+ B4 S) P};
1 U) ]. g' v' E \6 X- k7 n
& ]+ B5 A8 [6 i9 S3 p" r' k0 n4 n9 S
# E. C) \- q9 l" Z; {
7 G! J- B* Y( z2 R1 s# c
0 G) b/ m9 ?. E/ aclass CUPnPImpl
; l* e7 w9 r, o L{# `3 @6 X' v- |8 {
public:+ ^- K3 z3 s" F
CUPnPImpl();. d' Y. Z1 |, b5 g
virtual ~CUPnPImpl();5 v- C% k" Z0 C: _8 B
struct UPnPError : std::exception {};
- Z+ b4 K2 r5 [' Z9 [, ` enum {6 y% e2 F) p. w& t
UPNP_OK,1 v- j/ s- i& j% e$ b. B; [ r& n
UPNP_FAILED,
8 W4 E. }* S0 w9 w6 c) C% M UPNP_TIMEOUT
$ H7 o2 N5 k# a: x) c };
' H9 Z n, u$ g" G Q, y) Y2 b" S5 Q. ?8 u( {7 K+ z$ |/ ` U
8 f" ^3 l/ @: C9 R1 t, |$ n virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;9 S3 a% [) O* I N
virtual bool CheckAndRefresh() = 0;$ |* B: r& i E+ s( h
virtual void StopAsyncFind() = 0;
3 ~4 E; u, Z* Y7 u- [2 }! B virtual void DeletePorts() = 0;3 t8 \/ l8 e- w" ~% I
virtual bool IsReady() = 0;% N5 A, q( {: N; m' [9 u
virtual int GetImplementationID() = 0;6 b7 w% ]- ^9 e( @# Y/ B& `+ H
, @. f: c5 ^9 t, L3 e3 z. O& z void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping* Z6 w8 ~9 c( |2 D
K5 s( D& e9 u+ C4 x9 y, n
3 [; U3 z5 s$ `% U; F5 w void SetMessageOnResult(HWND hWindow, UINT nMessageID);
# ?4 {& B$ ~ f4 u7 R0 y/ { TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }
. V% [$ o) i- H" ~3 W: T( o uint16 GetUsedTCPPort() { return m_nTCPPort; }1 W5 j" W% l5 n( }) j, @4 G9 ]0 v. R8 I
uint16 GetUsedUDPPort() { return m_nUDPPort; }
* y2 t/ K# x; {; K# h0 Z: q% v2 X; ?/ E% W% F, t
( J( \! D% n E! H// Implementation
7 j9 z q0 S, d! D' Nprotected:
5 u, C7 X9 h# E volatile TRISTATE m_bUPnPPortsForwarded;
3 R V+ E" R+ h% g$ H void SendResultMessage();
e5 @1 z) s, S uint16 m_nUDPPort;# w) k4 ?! l3 R
uint16 m_nTCPPort;1 K% P- V/ O5 x: e+ I4 d% n6 R
uint16 m_nTCPWebPort;
/ S, A+ {# m) Y3 | bool m_bCheckAndRefresh;5 B! ^: F- l5 f& s1 p, u
; Z3 R. N6 J3 I! X$ z5 ?
% r: J4 z9 ^- [. A: P5 g, q
private:" h3 O: U/ c" V X- n
HWND m_hResultMessageWindow;
2 M0 m* O$ a; g( K1 r UINT m_nResultMessageID;% @/ Z! x+ D/ k* S" |( G) c- K. C& V5 q
: H+ b7 z2 m& P9 m4 B& U. n
' G6 V' u4 y% l* L
};6 q# M; q% A6 p& i
K6 V# y+ Z8 `/ S
! c. I% Z' T4 W( X3 e8 ~; y: o
// Dummy Implementation to be used when no other implementation is available
" I6 F8 }9 I* i6 D9 Mclass CUPnPImplNone: public CUPnPImpl
) O/ g; j8 K: M/ _8 N- u9 ^5 y{5 i$ |* E& w8 T3 I
public:% k1 P: x. ]; \/ E/ U" i
virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }( u8 M0 Q, |+ j: s( i/ S$ i
virtual bool CheckAndRefresh() { return false; }
, W. ]2 E$ f5 d: `$ L/ e virtual void StopAsyncFind() { }
1 a" V; J8 [% g+ T virtual void DeletePorts() { }6 T, G. d j% ?! t5 i
virtual bool IsReady() { return false; }
/ D) e% Y1 Q9 y8 f virtual int GetImplementationID() { return UPNP_IMPL_NONE; }
: m' V5 b7 U: j* t+ Y};
+ Q( }7 G+ M- l/ h# H
2 a5 }0 f2 }7 T: R% H
& z: P6 T+ E' j+ J( b/////////////////////////////////////" E6 `6 v& T1 w* t% ^2 F8 [
//下面是使用windows操作系统自带的UPNP功能的子类
( Y$ X5 y- A+ m: l7 Q: [
: c& W3 K0 }* p" `) \" g# L- A# V' `; N) Y5 K7 w; J
#pragma once
$ G. I/ C, Y( _/ ~" E7 V#pragma warning( disable: 4355 )
2 q0 w2 R4 g) L5 G: p3 F4 q0 U S; S( y- s& k
/ p' {6 j( g0 X/ O s9 a, X#include "UPnPImpl.h"6 y, `# E) p% [6 _, |2 R+ r8 F
#include <upnp.h>5 e" b, t3 M7 T
#include <iphlpapi.h>
& X* ?6 W2 i N#include <comdef.h># P/ e& v5 |) J X1 ]$ n% C
#include <winsvc.h>
2 c! h. w8 I- F4 ^0 `7 \4 S0 P( u0 K3 {* x
/ w! @" g+ U# [' r* L2 ` u( a0 {
#include <vector>
' K+ o8 b3 @( a( ~/ ^$ T#include <exception>
7 x: @: a5 d0 f" K; |) m3 p; r/ S#include <functional>
2 P! U1 M% K/ u9 n* I
+ i8 R, G4 h( _! v" O9 t' s6 }) M, W
0 Y2 x3 ^8 u) D- L+ a. p* e6 Y, [/ }
; n: |) J5 ?6 ^0 m
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;9 f& S. U' O* q- S7 F2 I
typedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;
' C3 a6 I& D& e. H2 b6 A$ Jtypedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer; \5 F" A1 k! M
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;
7 [% \* E8 |1 x+ W8 \typedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;. T9 C/ B! U/ J- q- ^5 G t
typedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;
0 H8 A5 |5 t& `7 I4 ftypedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;
' V# a; S& P) H' Q
U8 W% j7 v9 D. g' J9 F
5 m% Y- U* j% i8 N, y$ ~typedef DWORD (WINAPI* TGetBestInterface) (
* T4 Z1 `( t* [) R$ i IPAddr dwDestAddr,
& C* W3 |7 Y9 F PDWORD pdwBestIfIndex
. `0 y1 L6 a% M$ v4 N4 }3 Q);& b i% `' O, ]& U1 D
; ~, z7 y7 N, O* z$ }
( S( ~; b6 S; T; B( v3 a7 rtypedef DWORD (WINAPI* TGetIpAddrTable) (& s/ N2 K8 K$ G7 D
PMIB_IPADDRTABLE pIpAddrTable,
1 { j+ A7 G6 I$ M. s9 y PULONG pdwSize,
( f+ x! H$ G# @; o6 t BOOL bOrder
, h: D6 \0 X/ B( P);4 K, `& |* e- @9 I( N2 x. o$ V& B
3 b) D* O! o( ~' b# R2 ~5 [$ L% ? n: @ I
typedef DWORD (WINAPI* TGetIfEntry) (
( ]9 L0 {, J; n# L PMIB_IFROW pIfRow
+ a$ R; u) H) I# Y);
) B8 @+ J: q9 X. J; ^
! W7 W7 u' [2 V2 ]8 m
7 q8 r7 y) \7 J" qCString translateUPnPResult(HRESULT hr);
' e% Z9 B% t& v: M% z( A$ AHRESULT UPnPMessage(HRESULT hr);3 R+ g+ c8 N- C/ D6 W h( N
* M6 I4 [; u1 d2 L
1 M9 U* z0 }% m3 K5 Iclass CUPnPImplWinServ: public CUPnPImpl. K4 ~9 F: X2 P7 Y& D
{! r' Y7 I( E, e
friend class CDeviceFinderCallback;9 R3 ~! _' z w
friend class CServiceCallback;
* r- K" p0 k* [+ T2 x// Construction
1 x" p9 E' i1 e' q6 u, n% Upublic:* r: }, n2 s5 [1 ^/ J2 K' c
virtual ~CUPnPImplWinServ();. H( X6 O- w! ^2 B4 c
CUPnPImplWinServ();4 C( [6 Q) M+ A e r
' t$ I0 z% I2 R0 m X
0 i1 G: B- X: M6 t. V& A6 }* { virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }
: X9 a' s3 j" ?# u$ ? virtual void StopAsyncFind();5 D2 p# T! ]; h4 i8 F
virtual void DeletePorts();
+ X" l9 {! e( k7 e virtual bool IsReady();
3 m y6 ~: D. |) n virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }1 P5 h6 P: H5 R- t1 d' ^2 g" @
3 L$ {$ {6 p) u+ ? w* f# P8 {
1 f4 X- P1 j* h# }
// No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)
$ F" d, c+ k' F. T |( w // the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later
5 h* i {% O& e* i. y virtual bool CheckAndRefresh() { return false; };
1 ?! o" J$ B; H, s. x! C, X
+ a& e9 W% Z9 H0 y8 a4 w
7 g* F+ {- I: z- n/ X- a" a4 uprotected:7 Y5 A5 D2 }$ L( g* G [% `; t
void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);7 E0 R% n( F9 T& J
void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);$ U+ S% y; B0 b5 M( K. T& A
void RemoveDevice(CComBSTR bsUDN);
7 s; {" X8 z/ d9 R# | bool OnSearchComplete();) v g1 p3 U( I
void Init();
" m/ D2 Q% ?6 u
5 ]# D- H1 j, c. |( n! K2 d' T' s4 [
inline bool IsAsyncFindRunning()
1 c+ ?* P- s. B {
1 j$ E: R2 D3 n2 h- V- o' L2 s D if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )$ N( ?/ W) G- u! G' s( Q2 {
{& Y/ F5 }5 i! H& A2 J( y8 g, C
m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );
+ i1 O" E+ s* g8 | m_bAsyncFindRunning = false;/ b$ r# ?3 o, ?6 j# M3 a
}( R. b- o5 |- A% B* q+ K
MSG msg;, W7 i1 B/ o% J3 v, P; V; x( O
while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
! a1 a) o; z& S7 v5 ^8 q( P {- N* d8 u/ H. c2 ]) c! \3 l
TranslateMessage( &msg );
7 Y' Z# \1 R3 m8 ^, V0 ]% d/ I# I DispatchMessage( &msg );
; K- ^* c4 M8 X: x }
1 m% d5 E0 e2 X" c# {) M6 W return m_bAsyncFindRunning;
) E* k7 W- X- d2 g$ Q }
& d5 Q4 N6 J) T- E& G& c( b
( S; K4 @# \3 `5 `! D- t" q; S2 M
6 [; Q* P4 C7 p. U TRISTATE m_bUPnPDeviceConnected;' X% Q; G, A" {. Y1 k/ z* V' C3 E
/ ~4 p' q# O! [9 u' }( a
0 v: z! G7 C9 D5 O& u: R
// Implementation
6 x8 d) J: ^6 T$ T& _ // API functions
9 J* A& M" y; \ SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);
# `8 E; J. |' M SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);
! ~: F3 {2 {( W# h: J% w, ] Q BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);
8 g' B9 a0 `' ]( _8 t5 L0 M BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);
& l1 f, ?3 K+ F: Y: V7 R. t BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);
; v( k3 `8 @0 w% e# q BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);
* w) f K7 [1 X
5 M$ O+ o1 ]: C( M J Z1 L- r% G! i0 R" t2 ?' }
TGetBestInterface m_pfGetBestInterface;
! w9 H- }, S$ q" z) M TGetIpAddrTable m_pfGetIpAddrTable;
' x* Y/ L' ]; G6 ]7 Q TGetIfEntry m_pfGetIfEntry;5 U1 U' ?0 i" \. O
( ^$ J: G x1 j$ R7 y
% X' @, B) B" N, T static FinderPointer CreateFinderInstance();
3 R0 l9 Y. f7 \+ h$ r; b struct FindDevice : std::unary_function< DevicePointer, bool >
* _8 g$ X+ ]- e. D {
& K/ u, w. o B6 z( R7 F FindDevice(const CComBSTR& udn) : m_udn( udn ) {}
3 H6 H+ R4 ~% X result_type operator()(argument_type device) const( L4 R% e! [5 L" D4 Q9 w
{. v0 k" @2 ~* p4 y( t
CComBSTR deviceName;
0 h* ^: R5 _3 r/ @! |- b HRESULT hr = device->get_UniqueDeviceName( &deviceName );9 ]& {; |4 b" g9 K4 _: a. ?
! d8 U: b" y: I4 d- P, h0 x0 D$ c
* H) E" w C5 Z: c
if ( FAILED( hr ) )& X+ s. O) m- L6 q
return UPnPMessage( hr ), false;7 M9 b7 x. O( I1 c! f8 D, I
% m" T# n! T! A. z8 }4 \; K6 ~
& p/ A% u2 C2 Q) o return wcscmp( deviceName.m_str, m_udn ) == 0;
" r8 b& \. Y/ y }; R9 ]' S( C) Q
CComBSTR m_udn;
, K% \% z# F: G8 K2 c- C };
2 ]/ h5 l9 t% D3 z
- ^% E$ y! ~1 v( d3 p4 \* o, U void ProcessAsyncFind(CComBSTR bsSearchType);6 r! m/ h8 z( b. Y
HRESULT GetDeviceServices(DevicePointer pDevice);% v. l; M8 g; V% i
void StartPortMapping();' [% `7 g6 l/ l6 Y$ Y" s
HRESULT MapPort(const ServicePointer& service);" |, |5 G" T6 h, O3 W
void DeleteExistingPortMappings(ServicePointer pService);
6 r3 L" o# [( c- M void CreatePortMappings(ServicePointer pService);8 t+ N* t$ K. U7 d
HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);; q. y1 f1 _3 A7 P) p% \, [& T0 z
HRESULT InvokeAction(ServicePointer pService, CComBSTR action, / u) \ B: ?. C1 I2 Q1 }# G
LPCTSTR pszInArgString, CString& strResult);8 q1 h3 k4 c8 z
void StopUPnPService();
$ X! \# j7 [. {1 F) g
- j4 }4 r) ]8 y: R
$ q% s' I6 |' F9 W' i6 y$ G // Utility functions' c! t; m3 I4 [- R, O
HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa); N! y! F6 ^2 q6 e3 U! s8 }0 w
INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);$ b6 c4 l" @% l* ~; ~
INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);
: t- a; W% S% J8 F1 s* V8 x void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);* G/ Y! P+ A. X! i$ P6 C' X3 Q1 F
HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);
" Z/ W4 q* L2 [5 c& o2 Y, _ HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar); E2 w7 Z. c/ P6 f
CString GetLocalRoutableIP(ServicePointer pService);( O1 {6 H, c- Z- J) A9 w: m
8 \ h; T" {( J( I
/ T- Q! M- r' C, k* [
// Private members
: c6 w8 w4 v: c- n7 R4 B3 q& W5 kprivate:
" |+ k- _/ ]( Q/ D/ P! u# _2 s l DWORD m_tLastEvent; // When the last event was received?
e- k# w8 R* r std::vector< DevicePointer > m_pDevices;1 @. I _- W3 A3 v: ?- g% x
std::vector< ServicePointer > m_pServices;/ r: a4 c/ Y8 }4 L' `$ _6 I
FinderPointer m_pDeviceFinder; Z! u \: y% ]! G
DeviceFinderCallback m_pDeviceFinderCallback;
' @1 v& B9 b6 i+ ^: J' J$ i/ ]* v ServiceCallback m_pServiceCallback;- C& g2 z3 _1 ]8 ]
* ^: ~4 @5 g v! t+ M" \8 Q
* Q9 k3 f/ }2 h8 m LONG m_nAsyncFindHandle;
6 o2 j/ {; X- c2 d; y* ]6 H* T: d bool m_bCOM; n/ ]1 I- k4 t0 a
bool m_bPortIsFree;* r% ^1 Y5 b% H6 {4 k) B
CString m_sLocalIP;
4 E) _/ R1 P5 n CString m_sExternalIP;+ G0 f" t) _) v( U: v+ i( _( t' L
bool m_bADSL; // Is the device ADSL?; n, t/ h# K9 L' ^
bool m_ADSLFailed; // Did port mapping failed for the ADSL device?( d4 P: A& i$ E( L- ^; d5 U
bool m_bInited;' |. w& C9 I4 s/ {/ y- A/ {" m3 d* C
bool m_bAsyncFindRunning;
% J$ \4 z8 V1 U" m HMODULE m_hADVAPI32_DLL;% L; d) x- C5 j
HMODULE m_hIPHLPAPI_DLL;! J) B$ S' T6 W3 l1 r
bool m_bSecondTry;. l- u! t) v4 W! z1 \+ r8 j
bool m_bServiceStartedByEmule;
3 p" i, Y! ~. E5 r* M! s+ ?1 ~3 H bool m_bDisableWANIPSetup;
0 l7 `4 n( b) a/ w/ m bool m_bDisableWANPPPSetup;
7 ^. z7 r7 B2 H* \6 N8 m8 {
7 H& {( K+ h8 l" ]" _% p( T! [' Z" z! L: i5 J( e( S/ q
};
[! l# \& v4 ?3 x
: t. }) z1 F5 p! n; T5 _
& i) e' u- i; c( d) H8 @7 f// DeviceFinder Callback3 H+ k5 \* }" }" j# U' Y+ t
class CDeviceFinderCallback
* \; _3 b* ^8 W : public IUPnPDeviceFinderCallback
( t, q( b3 ] N% R& c{
5 `- U8 {3 v* s# ?public:
7 |' C4 c& \( A/ X CDeviceFinderCallback(CUPnPImplWinServ& instance)
' O! ^) `$ u1 v4 G7 D/ v : m_instance( instance )
. V( v" h. S. \ [ { m_lRefCount = 0; }4 l! e' d6 |/ [1 U* X
* g9 D0 N( y" y* d* s0 ]4 G
" z: B# L( l9 t- h9 [. P STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
6 {6 M- a7 S+ t- |, ], P* `' y STDMETHODIMP_(ULONG) AddRef();4 r l: t) d' h4 }
STDMETHODIMP_(ULONG) Release(); @5 s( E% a- p( a
( I# d) m1 i; ]' V& j }9 X
1 [: y7 o9 P7 z// implementation* r' x: w1 t; Z( @7 r
private:
. O. T, z1 \% n7 p HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);2 ?' q6 V( E- @- s2 O1 z6 M9 u
HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);
/ y! h% q# E3 u8 P HRESULT __stdcall SearchComplete(LONG nFindData);/ o+ w9 |0 R" m* T* ^
0 e) ~, v- R/ d6 a$ A& B5 e" Q
2 e0 F2 V$ p+ Y: }0 gprivate:6 Z' R6 P3 F8 w
CUPnPImplWinServ& m_instance;
6 k" f0 Q4 p$ f# M5 P$ R LONG m_lRefCount;
) G; r6 \) O$ f2 U( r};% d( V v2 [- `) V4 u G, _
; K: B# h1 R+ T0 o8 m% ~5 ?% F- @ l8 P6 R& @) e4 {7 U H. ?2 K
// Service Callback # ^8 W; R, @5 ^4 R7 G( e
class CServiceCallback
: g Z8 B+ b# B1 A- g : public IUPnPServiceCallback/ \2 U4 D! L/ Q- S6 w: K
{. @) p! E1 L7 G0 j
public:
* D _' B7 l6 j CServiceCallback(CUPnPImplWinServ& instance)4 d5 D% s# P. n \
: m_instance( instance )
3 C; O7 N3 d5 ` e; ? { m_lRefCount = 0; }
; U1 x3 _, a' }6 E9 r/ g; N( |$ n / N0 k, Q7 o. R
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);. X% l2 H5 E; J2 M
STDMETHODIMP_(ULONG) AddRef();" p0 U |7 G1 s. x+ Y8 \( L) \
STDMETHODIMP_(ULONG) Release();! R) l1 V" |/ e" O' m- ^0 v
9 Y" H1 Y0 Y0 i- S/ S* T% @ K2 {% P6 j" D# N
// implementation+ ~7 O3 z. ?3 W, e9 r% Q$ F
private:
, J; g2 c3 v" \6 o) S" o HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);; J* n' k+ o6 h# y4 W
HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);
6 k# J% v- o, A, E1 i' h$ P; n% D% l9 B6 k q. l
% P, a, |, [7 I5 T& y5 \$ \private:
$ K- {) N& d% I1 }% U c: Z CUPnPImplWinServ& m_instance;
8 C; z% F3 k: L. | LONG m_lRefCount;, ~5 k9 W8 A3 u. s v
};
7 e5 \4 z6 X4 q& x+ I' n' k: p. M! v1 g, ~. d4 r3 }( n
/ `$ g7 k5 d# \7 @% B/////////////////////////////////////////////////( f1 u" F; k5 b; T& T
7 _5 i* E% g T7 T. X% u- x1 k% k% f# |" p; E- G
使用时只需要使用抽象类的接口。
9 p8 `" ]: e5 L: k9 ~. S% U3 I" CCUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.
2 }8 S2 a3 L+ _1 c( b& KCUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.! Q N% v9 l- N* z
CUPnPImpl::StopAsyncFind停止设备查找.* J; ~/ c S1 S9 G- |. h
CUPnPImpl::DeletePorts删除端口映射. |
|