|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule,) u3 F$ j' k: w- f" Z
* `) c( m8 l; ^2 D4 A/ b' w, W
9 Y# q0 ]* g L& T///////////////////////////////////////////
/ X: g) S" ~- Z% P: S4 V3 B8 V5 {//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.; O1 p7 y3 ^) N. E$ e1 N \! w6 K$ g
: [# v8 V2 h9 ~+ e- _
- {, H: @9 q* {" i* w7 Y6 R, a
#pragma once# G+ S# i: b+ H& b C% y" y
#include <exception>1 C. d* @0 v) a& m
# n% T& ]: W2 A( z/ _+ T3 L9 g5 n( r8 `2 M/ p5 C$ w
enum TRISTATE{
2 a+ A- a& @6 [- j7 n TRIS_FALSE,* \$ |) o2 j3 ^& r1 ?% [0 p
TRIS_UNKNOWN,5 F' l( J; Z0 i! A, ] F) O
TRIS_TRUE
- i1 D3 _4 y3 j6 g" q* A};
6 l# C# u! i* H: p2 E$ a3 x+ r* Z" v0 L5 ~: R. C
8 g$ G' a* y" u( Y1 qenum UPNP_IMPLEMENTATION{* z. |* P. p: z8 ^
UPNP_IMPL_WINDOWSERVICE = 0,, d9 z! R$ v2 g% w9 z$ {
UPNP_IMPL_MINIUPNPLIB,' o4 s- b! b$ n: g
UPNP_IMPL_NONE /*last*/
3 L6 }0 {, ?+ b0 s% r( c- P};( @ |1 X9 W8 f% k! k5 e- V
, k6 p6 v& n% y, F' u! r+ u1 x e% P Q
; {4 e# r1 @& m2 v9 @# _6 S7 u: j( ~
class CUPnPImpl
+ U. b( V: M% ^* _{: Z1 J$ Y- h( c8 \
public:
6 ]; b/ b5 u: k) T8 v CUPnPImpl();
$ h) b- y+ y4 p+ v8 Y* t virtual ~CUPnPImpl();
3 v. A# T( _( x* `7 ? struct UPnPError : std::exception {};8 |1 y( Q$ h e
enum {
- l) s, T3 s+ c+ t$ j UPNP_OK,) r/ Q4 F# D: X+ K4 [, r/ Y7 J+ w
UPNP_FAILED,
Q3 [# H6 p$ }. U9 t- M9 D UPNP_TIMEOUT" x( i( g4 f/ J& [1 T- s0 q- W O
};
/ n( i8 \/ ]+ x) m1 R
0 Y( T2 M* }# {# P0 o( g7 c9 V7 [1 A: u9 g3 M
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;
$ m6 y3 I F) r1 c virtual bool CheckAndRefresh() = 0;
6 L3 d4 k/ L' t0 i9 d7 B" D: `5 } virtual void StopAsyncFind() = 0;0 H" K* r' i* _+ ?& Z
virtual void DeletePorts() = 0;
0 r2 H, t; i5 | virtual bool IsReady() = 0;* u H: E+ ^4 C
virtual int GetImplementationID() = 0;
: a- }; K) }# ~, |, S + p! I# j* t4 W* r2 ^
void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping
$ {, g) e$ Z2 c7 u# w; @
; V0 ]" }9 ~4 r
+ C2 ]2 ^, C0 [4 u void SetMessageOnResult(HWND hWindow, UINT nMessageID);& {/ J6 V' V. g- V; i
TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }
' \3 p: D) y; d% a: Y uint16 GetUsedTCPPort() { return m_nTCPPort; }
5 S2 j7 \1 W9 d6 F F+ w6 Q* ~4 a# o! w uint16 GetUsedUDPPort() { return m_nUDPPort; } 1 Z2 h, h: f9 ^9 i( P3 E- ~! E
! ?3 p3 H; \/ W' D9 @! ~7 C+ k5 z# T3 E, J6 p& X9 |
// Implementation W$ l- m1 b/ T" K+ K
protected:
, @+ w4 F* t, j$ m" ? volatile TRISTATE m_bUPnPPortsForwarded;9 N) M( A- P9 O2 Q
void SendResultMessage();
1 i' h7 R" U1 ~0 c( J uint16 m_nUDPPort;
1 d$ d1 V% l! ` uint16 m_nTCPPort;
. s# L! A6 v! V8 ^# c uint16 m_nTCPWebPort;2 ?" N: s. N _& X9 n$ z
bool m_bCheckAndRefresh;
) [5 V* c' _8 v3 Y$ ~2 `0 P/ C
c7 o( c- W; n# C& D/ E* |& A
private:
3 B8 H$ U7 b% _. Y, i) ]( c ]8 J HWND m_hResultMessageWindow;# W* j! |' T$ T# s7 \/ Q
UINT m_nResultMessageID; K2 Z, [" ~4 U* O( C0 D; d) ~3 }
( b2 u7 d$ p2 F2 i
: S/ e0 X+ `3 w/ z};3 n5 E4 y& X! a( z* a; f% h
2 J, w" Y; v( v1 N: E5 D. R
3 V! [- J: [1 ]2 s$ [// Dummy Implementation to be used when no other implementation is available) }9 L! e" o; e" [! F6 e
class CUPnPImplNone: public CUPnPImpl
" C' E, ` H+ ~% O{
4 ]. |4 V5 E( l) g3 S: ]: U cpublic:
5 X6 W* u) C3 v6 | virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }% o- u; ^; S8 U2 J. y5 Q3 h9 l
virtual bool CheckAndRefresh() { return false; }' m. w/ Y. t7 ?( e0 l
virtual void StopAsyncFind() { }
; F+ n$ [/ Q) m+ Q, f virtual void DeletePorts() { }* i( H/ s" N- Z- w. \
virtual bool IsReady() { return false; }
6 O0 Y' q. @8 s: Z! p$ _8 B virtual int GetImplementationID() { return UPNP_IMPL_NONE; }7 I3 b! _( `6 J+ d" a ^
}; m) b- v( J+ }; W- S
! ?1 f9 l. k& ^ }/ V6 z/ j# [3 K0 Y* b' q5 O. Q( I+ H; M
/////////////////////////////////////' _6 E1 g8 Z2 g( e* z7 t
//下面是使用windows操作系统自带的UPNP功能的子类
& o/ g3 c4 Y" ~+ _8 M7 X- E$ g, k; G! D4 U5 |3 z
$ l( p1 I+ c; p
#pragma once
" t. t5 b8 y; q8 b% U9 u B) S1 K1 r3 [#pragma warning( disable: 4355 )
3 r4 l# ]0 P! L( x/ e. j: H6 p6 q
, J& t& M7 [6 I) V0 w; D3 j/ j) @* Q, Y7 E: e7 Q- Q
#include "UPnPImpl.h"
5 V7 Q5 r: c1 R. R; [#include <upnp.h>. R" W. [5 t4 ]( q
#include <iphlpapi.h>4 f" @% ~2 ]9 G8 U* ?4 z0 ^
#include <comdef.h>
9 l/ O/ E3 z; j#include <winsvc.h>
+ A( o! }/ s! E$ Z" K, F4 ^
3 t+ n* N$ I4 U7 }- k% e
/ L0 a3 q# P2 j/ W: g#include <vector>
* L; `" z4 H. _. T, f#include <exception>( G) T8 P) m$ j, e
#include <functional>0 f( d f# P1 @$ s& [/ T" N+ P
% t, Q& }" o& a! u, [, `1 \+ C, r6 _+ @% @- z
t) A6 x! K- V- r
8 r9 Y @/ m; D1 U/ U: q5 R* i6 Jtypedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;9 E& h: ^1 Z$ b$ a
typedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;
5 o- G& q- i3 s* Htypedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;" b4 v, T$ H+ B0 A* U8 H1 x
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;! S7 T& P. U0 _" A* D3 Q9 C
typedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;
# u9 s: t r( q7 H: [6 M' Z. }typedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;: d E g; G% t+ ?3 C
typedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;, Y( K/ Q4 c4 B( p
6 L; g5 }+ C% M, h V; }
6 Y& ] P% T% A8 }! M( Btypedef DWORD (WINAPI* TGetBestInterface) (! y$ ^1 p0 E/ T7 d9 G6 X* k0 B L( e
IPAddr dwDestAddr,: [, { P5 \# H" K% y @
PDWORD pdwBestIfIndex6 \6 |6 c. u. V" A) V& T( o$ ~
);- j' j) E$ z. X
1 i, i3 G! v* ?: @
8 U, c1 ^; F; }- K* x) Gtypedef DWORD (WINAPI* TGetIpAddrTable) (" E$ A& L% u7 A y3 l8 y6 X
PMIB_IPADDRTABLE pIpAddrTable,
6 z9 R4 K* r- |, v; x0 A PULONG pdwSize,
$ v l6 t- A: L, v* E; |4 t BOOL bOrder
+ p& U$ O6 K- j& N; f! [);7 i" G# v# E- e5 V) ]7 J" r
G2 T( p. J! L
9 J6 m4 Z, d+ k! Wtypedef DWORD (WINAPI* TGetIfEntry) (
% M1 h) d- X$ j% } R PMIB_IFROW pIfRow
# b' y% x" Z5 N. z5 Y9 v);/ Y5 L6 m& L/ Y" ]
0 s0 k& ~) }; p: ~
6 v0 D- ~0 k# D$ B- {9 O5 _
CString translateUPnPResult(HRESULT hr);, T& |# b' _# [7 }
HRESULT UPnPMessage(HRESULT hr);
! q/ d7 j; m3 j. s9 t, U& H. f
" G2 f" D0 C% w! S9 E- V* K1 C! G2 {8 u' B+ u
class CUPnPImplWinServ: public CUPnPImpl
) v8 r& O0 I w# d7 ~3 o{7 l3 b- n" ]% W. q0 ?
friend class CDeviceFinderCallback; r$ y" K) {7 f- ]* |! ?
friend class CServiceCallback;
6 A0 m8 P$ @1 T8 V/ G7 l2 ]// Construction% n; o) W. _+ w
public:' e) c7 j9 g9 S4 ?6 Y# w6 r
virtual ~CUPnPImplWinServ();
j7 ~7 |3 L( P- }& q6 o CUPnPImplWinServ();
: _% C7 H- P8 O) i% o8 ?% R5 J6 t$ E7 C5 W! r. u# w
+ b9 O4 f+ ^2 p virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }* A5 X+ S# I: M- ~- w
virtual void StopAsyncFind();
! P: t+ c1 B9 R* f7 \" B$ T8 `, O, K virtual void DeletePorts();' H, \) b; v* @. u
virtual bool IsReady();: z6 g4 r/ j9 ^% y4 p) g! L$ n
virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }
; C. u6 B: s7 {) p W2 m2 A9 g) @+ d% l) y2 i4 w) q: d* }2 Z( [% d a
' [' i7 X2 y4 L. l // No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)3 P2 O: a* C! e/ f, W5 L+ g$ h
// the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later
& T( ?3 t3 F# `8 T virtual bool CheckAndRefresh() { return false; };
1 x$ a# G$ T7 G1 A" h7 m4 a8 a; t' O. U# n$ h( M) x, i
: ]/ o8 }' X1 Z0 e( A K8 N3 ?8 Vprotected:
1 |( J' J6 U2 q$ c void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);) Q5 I" }, `2 F7 b' N# ~
void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);
9 _/ G; _4 B9 Z1 n* O void RemoveDevice(CComBSTR bsUDN);
0 x: ]1 Z2 z, ]% P/ f6 \ bool OnSearchComplete();
: R9 r5 R" E: w0 Z$ B, E void Init();5 b z$ P' g+ c* M% B) B* u
9 T1 r- c- n7 L: J% L9 v- T
3 u- k" V' H, h3 k0 {
inline bool IsAsyncFindRunning() 2 x. V: \5 U' g0 P/ Q5 N
{7 N# q1 R% m+ U2 G% W
if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 ) _# E! ]% @4 C0 R- F0 z+ c
{/ t+ M8 K" A: g( f4 j: q! `
m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );' [' F1 E9 j& z/ x9 M9 ~. H
m_bAsyncFindRunning = false;
2 ]0 k% n9 W( m, n8 S$ ]0 o9 v }
% y4 {9 l/ N+ {' k+ _ MSG msg;7 u4 } P+ M% p7 _' s9 j
while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )+ Y( i: E# R+ z( |& L/ u) ^5 o
{3 a P$ `! t- U& F* A
TranslateMessage( &msg );
% E9 B# @4 G. l DispatchMessage( &msg );
- A( U2 e) B9 l. y- R5 E8 _ }
$ P" [! O/ `' ] return m_bAsyncFindRunning;
. x' t$ g/ x% X2 Y3 Z }9 z' \: Z9 C6 s1 D1 Y+ \
% U$ _( {5 d9 m) l" f: B
" S0 a f; d; Y3 T4 K2 n TRISTATE m_bUPnPDeviceConnected;
; s, l6 z. A5 }
. {4 u a1 R! H* T% M3 \* O0 o2 W
4 x3 x# L9 {: H9 I; q' E8 U// Implementation
" M% y" e9 }3 O& @* [: ?+ d // API functions
; ~; n; I. Y8 l0 F- ?. r# G SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);
7 y2 k5 D( Z) I$ ]; s* b) u SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);
+ B: V& b( ^/ W9 s7 w BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);
) M: s( r1 z: q f+ u BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);
! q! R# s: U& V3 ] BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);
( ?) e, L' @" L BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);
6 I+ |; }1 d Y; N/ K+ ~6 f
b! Y: D6 b# i A) i. B/ a& C( {% @4 u) X
TGetBestInterface m_pfGetBestInterface;9 \% {9 `& w, e3 j
TGetIpAddrTable m_pfGetIpAddrTable;( O* M: @: p, X3 g4 Y* |- G
TGetIfEntry m_pfGetIfEntry;5 l; B8 f- J9 s5 G) @
- u5 Z9 u0 o/ B' j. D
3 Z7 i* }+ t5 b4 j. E1 v static FinderPointer CreateFinderInstance();
7 x0 D b+ O/ J) o6 b& k$ i struct FindDevice : std::unary_function< DevicePointer, bool >
4 q6 k x, \' u {9 O, v+ C0 w, @% `3 E, \; S' B
FindDevice(const CComBSTR& udn) : m_udn( udn ) {}: U- v m' @" X7 s$ V) }
result_type operator()(argument_type device) const
( t% y' R) G. O {
$ h6 H! p8 ^+ k5 ] CComBSTR deviceName;
/ t& `9 r: y4 q6 c& C HRESULT hr = device->get_UniqueDeviceName( &deviceName );
% m; V* y7 l. X9 x H9 b) k+ H
; C6 Y$ R+ N* K2 i! S. k4 ^6 e8 s4 s+ N. Y: [. c' w: y
if ( FAILED( hr ) )1 D# ]9 J! V+ b i; f+ f
return UPnPMessage( hr ), false;! s' X+ _6 O' b! L3 K8 U! |
g& q+ w, L5 r+ }* G8 I
/ F" ]1 J3 p$ t7 {" [+ D5 x return wcscmp( deviceName.m_str, m_udn ) == 0;
6 e; L7 C* g& q" f2 w Y4 Q2 ]% U }) ?8 {0 Y+ a* c, _7 S8 s# R
CComBSTR m_udn;
: a7 C9 S6 Q! r: `6 C! F( ^+ D };
( _% Q4 U& j. b4 t6 F / n( e) q2 V4 K5 L5 f
void ProcessAsyncFind(CComBSTR bsSearchType);, c+ K+ |- n/ l. v p) L
HRESULT GetDeviceServices(DevicePointer pDevice);5 p- Y' ?' J. A+ \- i( r
void StartPortMapping();
" L7 t2 V3 F- | HRESULT MapPort(const ServicePointer& service);5 S4 o2 j. ~" {" G# P- w/ c/ g
void DeleteExistingPortMappings(ServicePointer pService);
2 A7 i+ n% {9 ]2 _ void CreatePortMappings(ServicePointer pService);
5 ]2 z1 ~" \" t0 C# G HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);
/ o& |& z- X! n" r; w- h HRESULT InvokeAction(ServicePointer pService, CComBSTR action,
( O9 K' A2 g2 V! Z$ T% m LPCTSTR pszInArgString, CString& strResult);
0 n& y) Z |3 Q( }5 P) E. m void StopUPnPService();
0 S8 A- f5 I$ H3 ]6 q7 ^+ t7 p& h% Y7 K" R0 @
% \7 ?* I6 j7 t. o. I // Utility functions
& a( J, E& X0 g& N Q8 E6 r/ V: Q HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);. F& j) x1 F" R; N
INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);
! Q" k4 q/ I5 t INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);
4 ]$ {: \, p. _; t: X D0 } void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);# M6 [& Y) E+ f; l/ R3 i
HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);, a5 A/ m- I3 z- W. ]) h' K2 z
HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);
0 Y5 P( c. I) o# s8 F CString GetLocalRoutableIP(ServicePointer pService);" P" {' e2 @! m( u: c
+ y! s( y) z4 O( ?: n
, E+ T& w) i' u0 K; `0 t: M// Private members
' \0 |$ S( U, p# i$ Kprivate:
% r8 ^) A5 ]5 T DWORD m_tLastEvent; // When the last event was received?
9 ?& _$ ^ Y5 M std::vector< DevicePointer > m_pDevices;! c6 l% H2 \& H$ I5 e
std::vector< ServicePointer > m_pServices;
+ e7 A: f% v6 I FinderPointer m_pDeviceFinder;( z6 Y1 M/ \5 e! Z- j0 g! p
DeviceFinderCallback m_pDeviceFinderCallback;- D) n$ a' u& R' F% j
ServiceCallback m_pServiceCallback;& @$ q7 Q) T6 ^: w) } A$ A
3 n s K, G v5 ~: @0 b+ c/ f% u: C1 c, x# P2 _
LONG m_nAsyncFindHandle;
1 v3 h4 b0 u6 p) c+ a j+ W bool m_bCOM;
7 H4 y/ R1 r! s+ b$ H- l9 o- J* N bool m_bPortIsFree;
" ~* x/ p. I9 R& R% l* p CString m_sLocalIP;
# b" D1 q' D) g" T7 } CString m_sExternalIP;3 j1 T" T/ m' q, q3 a0 H
bool m_bADSL; // Is the device ADSL?
1 s2 g2 K! Z" `, c, }1 ~5 t" \0 C6 M bool m_ADSLFailed; // Did port mapping failed for the ADSL device?
4 m5 K, t0 t @- U' T6 U bool m_bInited;
, m6 o! w: P- {- k* B/ C- i bool m_bAsyncFindRunning;
- q) A8 z6 H9 m* M' H% `( P9 I HMODULE m_hADVAPI32_DLL;
( c* h4 n; W+ f' U: M" X' j9 J" r HMODULE m_hIPHLPAPI_DLL;
- J3 @ b" E3 t bool m_bSecondTry;
@# }0 x; d& I. g' O bool m_bServiceStartedByEmule;
" \. h! Q4 s+ a+ ^0 V; J bool m_bDisableWANIPSetup;& h9 J( a, P& Z+ q
bool m_bDisableWANPPPSetup;
3 H, C( c/ A: f( F; S- X
" u% o1 b$ q" z
$ f% ^' U; K! {};, D0 {1 l- C: }8 J0 v. l" p
0 G5 v/ { `# L0 T. T3 q
% l1 {! k8 x6 ]4 J
// DeviceFinder Callback. E" A& C7 O" `* ]7 ?. g
class CDeviceFinderCallback2 a& h( ~- l, h& U' ]' p
: public IUPnPDeviceFinderCallback: T) A E6 k, X6 \1 [: l
{% X: {5 y) V$ K4 ?! l1 }& T- {
public:0 S: e1 B, `8 l% e9 w
CDeviceFinderCallback(CUPnPImplWinServ& instance)
1 |, s1 \3 b# O- }3 E : m_instance( instance )1 H& S1 @/ [# s8 W' x }
{ m_lRefCount = 0; }
& X5 r7 K( x0 M3 A# E) W7 B- z/ n/ I4 _3 w% W
% J1 s7 N8 G, o- f- u STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
e2 e \, E, ]5 W STDMETHODIMP_(ULONG) AddRef();* M, k+ }9 X0 \* ]) }8 d
STDMETHODIMP_(ULONG) Release();$ J. M0 h6 v% }
! E! t3 ^5 g$ M+ h- i- c
# A5 D+ k, S* m( ]9 |// implementation
q$ t3 b6 G; D' tprivate:
: N& ~6 e: W& y% x1 V8 N4 K HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);- v: V/ P g3 a
HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN); L! t/ w* _, d+ e6 F
HRESULT __stdcall SearchComplete(LONG nFindData);0 I. l0 j8 r) G% v( X
1 ?3 A# d: ~0 l7 l' W1 g
' q) V: I5 t$ D' ?private:& t% i% D+ G; }
CUPnPImplWinServ& m_instance;
% o- {$ {( c; [& A' L; o* z LONG m_lRefCount;/ w* g2 J5 v7 {9 R; K5 e
};' I" A- e$ n+ a. s) y
3 F) ^1 H! J7 B' A! n/ ]9 x' |" D
2 {8 A; m" a. X% e
// Service Callback % [- T s( ^+ [# d2 Z7 ]
class CServiceCallback
: ^4 u* X' L3 ^; F : public IUPnPServiceCallback
: G2 S4 k# @! M- O4 i+ T1 |{1 u0 q/ k6 ]& X( {' m' ]2 a$ [
public:
! y) E( j9 f" Y7 m, {6 u CServiceCallback(CUPnPImplWinServ& instance)
p) o* h* s, s6 a# k& t5 p) c : m_instance( instance )
, o( N' k' s/ l$ M. l0 V& I8 Z { m_lRefCount = 0; }
& C: W6 r v% d
/ ^/ p5 L. m% T8 I$ v$ O STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
0 `8 i/ r1 j! a# L# o* m2 I STDMETHODIMP_(ULONG) AddRef(); ^5 o o; ]9 j3 k% ^4 \
STDMETHODIMP_(ULONG) Release();& r$ z! l& }8 L+ B; h
" x3 `. ]$ l% f9 {: s4 O5 a; t7 X
+ c% K! h% O* X( I' y C// implementation
7 J6 B. V+ C) H- j0 y6 @7 w8 gprivate:
! Q1 O' D' d) i6 y7 R: n HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);
$ B+ e4 Z6 m6 Y HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);: s M. `7 \1 b) u9 z" |+ J
6 Q0 i$ V g% q9 L: g/ v, ^, _' G% j5 V0 @6 |; e
private:
( v4 [* ^, y: A( d4 c" L CUPnPImplWinServ& m_instance;' ^1 U: J3 U- A9 J$ k" i) x
LONG m_lRefCount;. p7 a5 r: x- j- z6 a
};3 I. J! t' z* j3 x
$ ^6 C$ l6 n/ v7 p& P5 `! t7 L; C* w
1 W+ H1 A K5 b/////////////////////////////////////////////////9 Y; ?( ~- J% r, f% c5 I8 z
# P6 S% G4 f& u: R( d/ B( I5 R, _1 S h# P% c2 g; M6 t
使用时只需要使用抽象类的接口。
3 F& p, M* U8 RCUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.
& Q# }$ n: }- {" ZCUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.
- i) F$ ~& m0 J5 CCUPnPImpl::StopAsyncFind停止设备查找.
1 u b8 J7 `( h0 wCUPnPImpl::DeletePorts删除端口映射. |
|