|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule,6 y0 H! ?+ ?% ?, `1 `) X) d
3 j) k9 }) m. o% r6 T! R$ P
) n( s. [! c5 f- W( C
///////////////////////////////////////////" F9 G# T) e5 h& y+ d
//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.
3 t, l# F2 k! \7 ~
4 Y# @8 I" d; Z
0 G; X. n y D: T#pragma once. j% }$ k' m9 a( T) e( y
#include <exception>
0 e3 z! D% p, [! \5 o" {, c# t+ |) N6 L, Q" D" I
5 u3 C" K6 e Z; a3 i
enum TRISTATE{4 _1 [. q/ Y9 C+ L* ?6 _5 w
TRIS_FALSE,# Z$ d. v& L6 v$ j+ `
TRIS_UNKNOWN,
k4 @. {9 o+ d! t6 T- w/ r# C TRIS_TRUE8 q: ]$ R* d; J8 d. q
};
* M1 {4 R0 Z* C2 o P- Y* @1 {# F+ B# g6 Q M+ B; b
O$ x4 D, B' x p* y# n# lenum UPNP_IMPLEMENTATION{+ J/ M Q4 g1 _* j8 h
UPNP_IMPL_WINDOWSERVICE = 0,
2 K4 F. m: O1 I" c4 E4 i. f& b UPNP_IMPL_MINIUPNPLIB,- [- a( ~- x7 x4 k
UPNP_IMPL_NONE /*last*/" s0 V' L6 g4 |0 f) `' S. l1 Z) b
};
1 J$ y# K% ~$ a, N. P, F& {8 ^2 ]6 s9 X7 D; x
! g% @8 N4 B, U9 ?' T! V
5 }# P; u) s% W4 u+ g1 ^! R" _
+ v9 x( ]4 ^" zclass CUPnPImpl& I6 L, o2 r8 _8 d
{# `9 w5 O$ J0 Q" X1 ]+ G- V
public:
8 R/ A& i) z* z CUPnPImpl();* H; G3 v3 j- |/ o
virtual ~CUPnPImpl();
1 d3 g2 I* d! e9 {5 E0 N' h- I struct UPnPError : std::exception {};
+ d/ Y' y: M7 N# E enum {
$ `$ v& J. U$ ?- { UPNP_OK,+ h0 a8 \+ a5 e
UPNP_FAILED,9 [ Z/ p2 y. T9 w5 n( e5 ], E
UPNP_TIMEOUT' C; ?) ^# D2 Y/ ^) v
};, O$ K! N. {$ R: Z( S5 n3 U
6 x/ W, G6 Y5 y0 k! Z7 y @$ m6 P3 u: i& r% a- d
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;% x. T+ q1 E! F2 i
virtual bool CheckAndRefresh() = 0;
% ?" N3 J- \4 e virtual void StopAsyncFind() = 0;
8 K( ^% h5 w9 ` virtual void DeletePorts() = 0;
: S* N6 O5 O. c( Q virtual bool IsReady() = 0;/ k' y: Z) |& q5 T, @
virtual int GetImplementationID() = 0;
" s" H4 u5 Q6 F 4 n: g, X9 T+ Y6 k& y2 Y4 T
void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping8 A' A# U# K3 C1 m# E. P4 h
6 A/ t7 }# S# K/ S! L, w2 q
& A: V% F5 T, M7 d7 M void SetMessageOnResult(HWND hWindow, UINT nMessageID);5 b- {# g; c: D3 U1 C# ~) ^4 o# ?7 V1 `
TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }9 Q( ~$ G3 `: c3 F4 }# y
uint16 GetUsedTCPPort() { return m_nTCPPort; }
5 c6 W8 b H. K3 ]- }9 W& z) G uint16 GetUsedUDPPort() { return m_nUDPPort; } / L8 x2 x ?- k; l$ z! W8 e Y
' O" W x) @! i) S" h1 _# g# z. \/ W- a9 {2 h
// Implementation
1 J3 Q0 V1 ?9 U/ Fprotected:
- K6 _+ G1 C7 _* ^7 z8 l volatile TRISTATE m_bUPnPPortsForwarded;
; q! g8 V3 R/ t void SendResultMessage();
3 o6 f& o8 j. W. v) L uint16 m_nUDPPort;0 |5 s | H& [# O7 o$ y" S
uint16 m_nTCPPort;
/ A' T& V4 l. j6 B uint16 m_nTCPWebPort;% V' s, q2 h# d1 W
bool m_bCheckAndRefresh;, ^* B# J% k0 b1 _* `
+ c* G2 x" [* T. y! z
& [. k# U! T" Iprivate:
1 D# P! A9 D5 D HWND m_hResultMessageWindow;, a+ K9 Y. |7 | a7 N
UINT m_nResultMessageID;
' g+ \) M* y4 K2 o5 f1 X1 J
# F7 u, ^# E0 J3 k' i" G) V# T/ b4 N' ^/ S* n0 P, ?9 N
};( I; H4 R6 l/ m! A
& I* W2 f- N& F1 I2 z# G! Z% f
# O, q. @! ?9 }4 a8 G7 S- F
// Dummy Implementation to be used when no other implementation is available, h h' z# j6 q# H% {
class CUPnPImplNone: public CUPnPImpl
) K1 z0 G3 w4 f6 V4 K{
- F B) r$ V- E; q% Jpublic:. `/ Z- ~! C( D5 r+ u' q* y) R9 C9 S# r
virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }
& R7 {3 [3 A, h# G9 N ^ virtual bool CheckAndRefresh() { return false; }
) w x5 h f) x, p virtual void StopAsyncFind() { }
( V3 V/ {; o8 E" h! e, l9 G$ L virtual void DeletePorts() { }
0 b. X2 L( y- D( D0 j virtual bool IsReady() { return false; }7 A, \8 g; J. v9 w7 J
virtual int GetImplementationID() { return UPNP_IMPL_NONE; }6 D! B* T9 F3 z
};
) z, m: ?' s! y/ F
, M, Z- Q2 o( m9 m, {: q! ~+ H% F
/////////////////////////////////////
3 N) ~* ^' ^0 R5 t- B//下面是使用windows操作系统自带的UPNP功能的子类: W9 v& H) u' V4 S9 h2 }9 y0 V& w
" R- D# C: T) Y" x5 m- ^. r
0 `! o J" O1 j
#pragma once
! y' I4 C0 _+ `( @# W- k. u; @- R" x4 k#pragma warning( disable: 4355 )! F2 M: i& m" s' t! w8 w# ]
_2 }( f5 H0 @* k: |8 N$ B8 H& N& a8 h9 p: T6 W
#include "UPnPImpl.h"
% X, R5 G' m) D3 |& v#include <upnp.h>6 o$ M8 H6 p' ~
#include <iphlpapi.h>
4 k5 i# V Z5 T3 X9 G#include <comdef.h>7 R; W) \+ G: l* K: x0 V& X# F
#include <winsvc.h>" `7 i! K/ r6 ]- p( v# w& P
; S6 f. O0 l1 ]& X
" f2 x, _; H9 F* W#include <vector>; Q6 \7 p4 O; Z: A( ^) C
#include <exception>
' y9 i k, F$ L% C#include <functional>
2 F) O8 L+ C8 G! b
3 P9 P; Y8 D) f. f: n/ |
# x e3 f' z! N d- Q5 t1 y6 V
. ]2 q4 k+ G( `& \, J$ n" s/ B* k. v2 J" X. _. U( |
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;
3 y/ \+ S2 f+ R- etypedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;
, M, ~9 e% J0 x5 `6 ptypedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;3 p" N ?2 h- ]' u- T% I
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;
3 o p4 A- s% Ntypedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;
3 @" O8 m" H9 M. @* Q1 Ptypedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;
7 C$ k0 }) _3 D3 E( }, ~5 a/ ~5 Ytypedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;* `( t5 |$ K; x( d3 M
+ a9 [; B1 n* x! }
: n* t5 V5 K( Q( k; q" ntypedef DWORD (WINAPI* TGetBestInterface) (
7 ^2 |5 w! @5 R& u! D, I IPAddr dwDestAddr,& l9 K1 J7 u% E' Y+ i
PDWORD pdwBestIfIndex, ?, w5 D2 X# l" p
);
/ d8 M+ j! j! ^1 M) J# Y+ G
/ X2 ^) b/ F8 ]
i. W9 ?3 B. P. Z& J7 x1 k# @typedef DWORD (WINAPI* TGetIpAddrTable) (
* G2 \6 C! }/ c PMIB_IPADDRTABLE pIpAddrTable,
- A* `" i6 H; Z/ F8 x. g5 P PULONG pdwSize,! a+ n. q1 r2 l9 Y5 C
BOOL bOrder+ N' c, b) V3 ^ l$ ^0 l5 B
);3 i0 A; Z' Y1 l* \6 L1 b- |
( B5 u" A& G2 |8 S, B: C3 F) K6 @$ p- X; e/ N& |; K
typedef DWORD (WINAPI* TGetIfEntry) (2 u4 a5 H/ a+ X1 U: O
PMIB_IFROW pIfRow
$ Q! w( X O9 h);5 Y) E1 b3 f! b8 A2 e
+ m5 J9 }( c( U) d( b! I1 e
; y% M1 a9 X( l5 a' W* X
CString translateUPnPResult(HRESULT hr);2 H% v: i6 U/ H7 @% h
HRESULT UPnPMessage(HRESULT hr);, ~. _# T0 Y4 B" H- D/ W+ Q8 d) y
5 k0 V6 n: M% m- ~2 _+ f4 I) f
5 t, ?; ^' b8 V8 G" j- c! Sclass CUPnPImplWinServ: public CUPnPImpl! P8 P* l$ l: h9 ^9 o! V9 ]7 p
{
) N3 F/ b" i- R* w& F4 N- `% ^1 t friend class CDeviceFinderCallback;5 }" V7 H3 C2 N- _' _7 ?
friend class CServiceCallback;& l9 g4 [' n; |
// Construction
* T1 j* A) r% ?2 ]7 X7 V/ L/ apublic:
3 y. h% w/ `5 {& l virtual ~CUPnPImplWinServ();- W! ^7 r2 c/ P( J% m9 P$ G# F
CUPnPImplWinServ(); ]; Q; Z* E7 e4 L5 S
; o7 X& i5 V" D" h3 Z* z( W: E t. y- o+ w, r' K/ x8 L
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }" N& `7 M ^5 [$ | D: @: h" }
virtual void StopAsyncFind();
- h; [! a/ R- F7 \ virtual void DeletePorts();" R v! K6 w3 u' s* j
virtual bool IsReady();. m \! s _, e Y6 W
virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }
3 |% V: p& X: F! |6 w$ {2 m; C" o
]4 k& U, T% d- C0 U
// No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)7 \) v: {8 e+ x
// the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later
: B+ [) G- ^4 \: R h' U virtual bool CheckAndRefresh() { return false; };
* \$ j9 |7 Z) p" F5 ^2 x2 _
* Y+ C1 |6 z* o( J% r& m) j& K* N% b! ^$ z$ ?1 I- G9 D
protected:4 G" D# F$ n* `5 t
void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);" f( k ]. u" k$ ]: Z" O
void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);. `( j# X2 K3 {( }+ l" H
void RemoveDevice(CComBSTR bsUDN);
, ^2 J% K2 z) K2 G& E, L bool OnSearchComplete();
( T6 [0 s* a: l. Z void Init();
4 U* D: d) x( t% W" n) q- l! z- B+ r* l X+ |5 W3 {
. B2 y x w5 @6 @ M( r6 e
inline bool IsAsyncFindRunning()
& ~& b/ N; Y0 l. P {
8 u. |( S+ _5 J$ o, z9 u if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )! J) g9 Z( C) M& D& @0 a1 W& y
{
& a* \5 J( U8 n; n* l4 E m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );
, c, [" l0 `$ h: L4 Z m_bAsyncFindRunning = false;- X( E+ b9 p6 J& O9 n
}
_" F. y1 O* K1 @- w MSG msg;
: }, [2 }$ G5 X& [. o1 v4 M5 s# ^ while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
% \" ^/ N1 m( M2 c7 N8 ^/ d- W {6 T1 a4 w5 ?+ L; ?+ e! n
TranslateMessage( &msg );( }- h% D+ N" _9 o3 v8 ^4 _' c
DispatchMessage( &msg );. z! X7 {6 T" f- ?/ J. s5 O
}
& `# J4 U" k( f; ^ return m_bAsyncFindRunning;
( `2 o2 o' ]# }6 ]( x }. b# X' G" e8 X) ], }2 O& @) V/ b+ v6 n5 j
& T5 \8 r% F- A$ ?5 U3 O. v
( N3 C' p% k2 M3 U
TRISTATE m_bUPnPDeviceConnected;" a5 J2 G; o- O9 v0 I
( H) n6 U6 W! f7 J0 m6 i) o6 B& V( r- E8 r
// Implementation
5 D- n) f$ o x& G+ ?. H7 j4 _ // API functions, E* S2 {! Q" u# p& ^, @
SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);1 L* ^ h4 `* k
SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);' k2 @( P" f4 f( J* b" i
BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);8 E4 j9 X, c T, A2 L3 o7 L( |* C
BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);( j/ _7 a! h. h" E3 ?: R
BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);
+ z+ P( [! c* B0 v8 i BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);) `' z4 ?. J) \3 Y, T- H# Q
4 }+ w- D6 M d
/ `5 m, H; e2 {. r3 a+ P1 P+ M5 y
TGetBestInterface m_pfGetBestInterface;- m! b) @. Q6 p* Q& _
TGetIpAddrTable m_pfGetIpAddrTable;6 h' P9 u% l0 W; Z4 k1 j
TGetIfEntry m_pfGetIfEntry;
/ L, B; D) T0 n& K$ b2 h: p, T/ [+ K8 d. l& P. u
( M2 r8 u d [$ k8 m6 D7 g2 j static FinderPointer CreateFinderInstance();. S& y9 T0 O( @ X$ @* H9 ?# ?
struct FindDevice : std::unary_function< DevicePointer, bool >
5 M& P, f. Q% A0 @ {2 L: X% _, X8 |1 o3 j6 W
FindDevice(const CComBSTR& udn) : m_udn( udn ) {} k6 t# r: R% G A
result_type operator()(argument_type device) const4 F; E- Z( F9 ~, o. { k
{ |* D$ T) l+ T( e% ]: j
CComBSTR deviceName;
6 H3 s- n8 p5 ? R, i) y HRESULT hr = device->get_UniqueDeviceName( &deviceName );
3 T9 _( T6 z0 U( l9 K" J. C- }0 I, @
! W1 r( v+ L/ R. K5 s8 J
if ( FAILED( hr ) )
& J# }$ @! J$ [9 g9 }3 N$ V return UPnPMessage( hr ), false;
) v7 |) M7 i/ f B |. C& ?
# c. N: N( J2 ^6 }1 x4 ^- y8 \
* H$ w9 L' T& D" B6 R return wcscmp( deviceName.m_str, m_udn ) == 0;
; \& X X) A" m }
8 F+ q& a3 ~! v- |! z" v# q! S9 F CComBSTR m_udn;* w! ~, l: G! i( T, Y" V/ ?# ^# ?! p
};
) ]* d* k6 U# S9 C6 K @* f/ I6 F0 \
. v5 V! h( S9 n/ p- w4 ` void ProcessAsyncFind(CComBSTR bsSearchType);
, w5 T9 k3 n: N1 `- S! c6 q1 W HRESULT GetDeviceServices(DevicePointer pDevice);
! M6 @, d3 [+ Z void StartPortMapping();
2 K8 V( N" ^4 q2 z. I) O& G HRESULT MapPort(const ServicePointer& service);/ q8 R. ?5 s/ z% R3 W' r8 p% Q
void DeleteExistingPortMappings(ServicePointer pService);
. Y5 E: B5 d/ i void CreatePortMappings(ServicePointer pService);, E1 Z) k" ?, x( ~5 G! A, x( L8 e5 \
HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);$ q8 q- ~+ r& `7 x9 \
HRESULT InvokeAction(ServicePointer pService, CComBSTR action,
/ F' ]3 w7 _ q- x6 P! V LPCTSTR pszInArgString, CString& strResult);9 M* v/ ^! V: r
void StopUPnPService();
. O& E: G: h7 `2 a7 g* l# W+ U) f: x# |% g7 t8 U% m0 j- _" H
' k/ X3 K4 e+ K+ q2 U // Utility functions' H: Q& k, p# ]3 H8 p1 x7 S
HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);) `- v+ ?2 e8 y* U V: t
INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);/ w" D$ x5 T! d- ^2 L3 X
INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);
- H/ j1 @% ]2 m# d) ?% Y. P' z void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);
( z, }: i, @7 j# D! }6 m* G3 I0 H HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);
, y/ s. \. W% P% f C HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);9 Q& A; y" K$ i( K1 H# S% Z+ N
CString GetLocalRoutableIP(ServicePointer pService);
) ?3 o: c9 \1 A% T
3 z; H% ?( Q* C% }) D9 H7 z8 ]( M
// Private members
. \: T: d9 b6 }, p8 d4 x: Wprivate:: |; O/ ~0 r/ h/ q$ k# i% i- X; q' b" T
DWORD m_tLastEvent; // When the last event was received?9 J6 r3 q7 N c; M$ @; m6 w% w
std::vector< DevicePointer > m_pDevices;
( E# X+ b( Y7 W( `$ U std::vector< ServicePointer > m_pServices;
% U+ Y" S7 z7 W, V0 K( j FinderPointer m_pDeviceFinder;' [: {+ D' z3 M" G$ E) T
DeviceFinderCallback m_pDeviceFinderCallback;5 J6 a0 l/ i. ]) K
ServiceCallback m_pServiceCallback;
8 k7 W- G5 A& j, } e: q+ i5 z* M V% x( @& C
7 `$ S7 a0 E' g7 I# B3 A
LONG m_nAsyncFindHandle;
% S2 E( e$ Q6 U, R bool m_bCOM;$ X) U: S4 Z8 ^! Z
bool m_bPortIsFree;
+ U6 F( t e" L( q, z, _ CString m_sLocalIP; q4 Z. j% D/ }1 B
CString m_sExternalIP;" D; T6 k6 x3 f: g
bool m_bADSL; // Is the device ADSL?1 C1 }$ ]) B3 E
bool m_ADSLFailed; // Did port mapping failed for the ADSL device?
- ~/ ^6 L) e F& ]2 n' S9 | bool m_bInited;6 [* w9 w& S( R: I
bool m_bAsyncFindRunning;. D# G- ?( ?# ~3 E
HMODULE m_hADVAPI32_DLL;
" A+ E0 C$ g1 Q5 F* I b HMODULE m_hIPHLPAPI_DLL;2 _2 |$ f/ @$ Y( H6 d
bool m_bSecondTry;
$ t9 ?" S6 E6 X s: D0 f3 j bool m_bServiceStartedByEmule;
. }# K. w8 b! b* @! _ bool m_bDisableWANIPSetup;
* l$ j6 E E- ~! V bool m_bDisableWANPPPSetup;
1 |& _8 h9 m$ L' i0 @3 L" `7 m
7 a5 r, v& O; \8 D3 \6 ]8 N1 Z. j7 t0 }0 O, Y+ |3 H2 a7 N1 ` m
};8 J6 g, `6 ~, e
/ w# R7 X) f% }/ w9 x8 `% k. L2 h. c! M; |4 `3 l+ v7 L5 k9 P
// DeviceFinder Callback$ X% U$ [ H q' {0 G
class CDeviceFinderCallback
1 _9 a7 |# `$ y$ Z : public IUPnPDeviceFinderCallback
0 a: r* l# P _7 \; Q% Q8 u{
8 ?0 s$ s2 ?2 cpublic:
& Z' ]* G7 @) K CDeviceFinderCallback(CUPnPImplWinServ& instance)
5 Q* K* ^4 S H6 t2 R : m_instance( instance )
5 j- x% B2 @3 Y0 H" a( I { m_lRefCount = 0; }: z# N' b; _6 n7 p2 A
5 t) R/ v1 y" s; L
7 t4 p0 }0 T7 N" g7 P4 a8 j STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);% V5 { {+ v7 b+ k( d' b0 \
STDMETHODIMP_(ULONG) AddRef();
$ i+ B8 o$ z5 { STDMETHODIMP_(ULONG) Release();
) h" E) k9 ]; q/ f/ ?% {4 I% V8 E' W( ^8 J
5 i6 f/ ~/ z' n: X7 [2 o1 m1 F// implementation% W! T2 y; i( @ a! a S
private:
1 Z0 b+ U0 _7 [" N( h1 |! p HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);
; l3 P/ Y! k# a HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);
4 `/ l2 U8 O1 l HRESULT __stdcall SearchComplete(LONG nFindData);
$ I! p" m1 \0 B$ B. q
3 {$ L0 S& r* O) T' I. O/ V) n: c- Y M- _. n; r! f
private:
4 T7 V1 j. d* U) y3 ^ CUPnPImplWinServ& m_instance;+ k( A; ^' t. `9 w5 T5 V, ^
LONG m_lRefCount;
! {- o1 D' Q/ O" T& v, M};( k b$ E) p( p- I" [0 ]( c
+ v3 S- g% S, g; Z! J; U8 t9 J
2 N0 Q. Y2 h3 r9 O" `. W// Service Callback
+ b6 e$ n% X; Eclass CServiceCallback
8 j/ ]7 | x' w i5 @. C+ B : public IUPnPServiceCallback
) K1 \% \3 k' S4 M- V8 w{
& A+ k( l( l+ W& L' }$ Z/ l D7 j4 w5 Epublic:% H* _+ o; f# U
CServiceCallback(CUPnPImplWinServ& instance)- J) H1 O; [9 E, l% t
: m_instance( instance )
5 c" u% y6 r) H' K { m_lRefCount = 0; }
! |$ [6 b1 g+ u" Y9 t6 O , T. t+ S S6 M! b4 b
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);, ]/ ~ M% v" o7 Y+ v L: e
STDMETHODIMP_(ULONG) AddRef();, z4 Q9 t' u2 w
STDMETHODIMP_(ULONG) Release();
& e% @ @) F7 p$ k3 Z5 P% i' {& c* A; F6 T. V
' t$ i3 k9 s% J+ [( {
// implementation
: S! j( v! s/ } [) G6 |9 s; M$ Xprivate:
4 ^/ c2 ~. X9 j0 R: T HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);
$ ?+ R9 U8 X, D; ?& w HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);/ H) I4 L& c E! P' K" X) R" s
5 [! D1 C) `0 U
1 u4 H5 v. `! ^0 N C
private:3 g- e% C3 I+ G* ]) Z! C
CUPnPImplWinServ& m_instance;
, ?% d5 T! W2 G2 q LONG m_lRefCount;
5 r4 z' v# K: B+ e& I* V; q3 d};( }; K' q$ w0 D
7 h( q! k" m7 _6 ^/ e* F2 y* a" _5 i, D
/////////////////////////////////////////////////7 y M% b6 N3 ?2 K- `2 e( T
) N% Y5 ~5 d' I z" D4 l
5 Y5 A5 N% S) S& E9 j3 w使用时只需要使用抽象类的接口。
, n I* ~; L4 X' f$ Q) bCUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.
3 m0 b6 g; Q8 U2 A Q1 jCUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.
% i1 ]- G- }: t6 yCUPnPImpl::StopAsyncFind停止设备查找.# n+ Y% U+ F+ b- z2 K
CUPnPImpl::DeletePorts删除端口映射. |
|