|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule,5 y; q: M1 p( b+ ~2 h p
5 Y4 T+ U* L4 q; [& m$ v, n) l
' E4 t: M4 m _2 G% f
///////////////////////////////////////////1 {( u" R- V" r2 L' ~& R
//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能. q9 d+ l4 D" U3 |9 X) ^+ e3 C
4 z3 E, ~* ^1 m, W+ G9 ^. S
2 i1 f3 i& M8 M% I9 Y7 O- K#pragma once6 h' ~2 v7 ~6 d: ^! _& g$ H
#include <exception># c! i' D9 o9 k
0 C8 u9 Q- Q6 ]
8 x7 A f/ p, F$ ^ L) x {
enum TRISTATE{5 ^ _7 u) j$ G" V- ]! M
TRIS_FALSE,8 ?8 a F( P. z) t9 H2 j; T: v8 |
TRIS_UNKNOWN,
6 h* D/ h6 G7 c i TRIS_TRUE# m# c6 y+ C$ v0 k$ r
};6 a# p- K1 j+ ]& c
- @0 }' A( E( ~3 Q* K
, X; ~8 _0 C- l/ Henum UPNP_IMPLEMENTATION{
" p7 x h7 c h' c+ U2 e! D+ r UPNP_IMPL_WINDOWSERVICE = 0,, s2 K) G* A, j5 r; [
UPNP_IMPL_MINIUPNPLIB,, w$ ]) i, @* @0 p4 j2 w
UPNP_IMPL_NONE /*last*/; J# I7 s, x+ }, A
};+ p c, p3 Y& ?; Y- K
, P L# q# T8 D0 W/ K5 ?. W1 z) Z! G
* I6 \2 J. x( \- a8 ^- A
- d ?# I" D# m( s3 n* E
( @- K( j' X# W2 cclass CUPnPImpl8 f/ @1 \/ {6 X* ~% o: C& f
{+ S8 C1 y( F- V" O
public:3 s4 P% ], `% z: M/ y
CUPnPImpl();
( D& E0 l$ k; a0 }) e virtual ~CUPnPImpl();
0 ]4 _. _- H! [& }1 Y. R struct UPnPError : std::exception {};# [ B2 e; b0 B% B! a: ~8 P
enum {
! V2 x& t" |- B5 w UPNP_OK," A/ G' u$ b- P6 y4 i' q7 I
UPNP_FAILED,
! D; w/ F8 X" y$ z& N& [; { UPNP_TIMEOUT
* ?" q" f$ D! N' ] };
- X& r+ v$ ]0 N- @
% l' ], U, D- B$ x* l& t2 z# j+ e1 Y4 e3 |
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;
9 v7 {% c; ?5 E. H virtual bool CheckAndRefresh() = 0;* l2 Q; U6 e5 ?3 l( I
virtual void StopAsyncFind() = 0;. Z. g- e! r1 I6 v, g9 a6 D
virtual void DeletePorts() = 0;
7 U. ?, C; O5 ~. [3 t" w3 V6 [ virtual bool IsReady() = 0;
) _& L, D6 P! A, s; F2 I virtual int GetImplementationID() = 0;" M1 @' ~; f n& \! q
, G( _3 D5 t2 v+ ?( m9 U
void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping
- M# F! O7 ]. g! d3 ~. d
# d5 F) h6 b( P, Z1 c$ O F7 o- w: o0 _: I: ` w) e7 W* V2 b
void SetMessageOnResult(HWND hWindow, UINT nMessageID);- a, J" @% o* o' d5 b
TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }7 z4 v+ o, |" L4 x3 r( @
uint16 GetUsedTCPPort() { return m_nTCPPort; }
5 ?; a0 H8 ]0 ^ uint16 GetUsedUDPPort() { return m_nUDPPort; } ; @' R3 k- O( E5 K& c/ v- `
& E. M$ }, y* w; o4 V0 Q
; { r+ S8 ]0 L
// Implementation
$ A7 g- I- O* G/ m eprotected:
/ H, o) u" G! A1 f volatile TRISTATE m_bUPnPPortsForwarded;& U7 x' I& A" A" B: s0 ^
void SendResultMessage();
# f1 q3 w t! [5 M. c4 h' d uint16 m_nUDPPort;+ n/ T, n/ v3 P3 H* s2 d
uint16 m_nTCPPort;+ J- V$ ^* _' U$ L! F
uint16 m_nTCPWebPort;8 \0 f. [5 j/ q' a6 o+ j. ^" o
bool m_bCheckAndRefresh;
8 s( `1 P0 k( O; L: c
2 @- u% O( v5 Z. z3 n& d, n% b0 @( i: E" P" y
private:- \9 a9 [" I+ t
HWND m_hResultMessageWindow;
$ H6 F" Q) o4 D6 K0 G% R p UINT m_nResultMessageID;: \: ^) I; T% J8 R1 P! M8 G
6 n8 C8 ?9 R& [9 J' H B
$ l6 M% ?0 L- A# u t& z};
! U6 M& ~% a* M# b: G/ Z9 h$ S8 ^2 e- W( ]
6 Z: X2 n/ K' i! e* Q+ V) d! y// Dummy Implementation to be used when no other implementation is available
a* f8 X' ^1 B! L, Q8 Eclass CUPnPImplNone: public CUPnPImpl
8 G# T* W8 Z: m7 S E6 C{
; ?; x, e7 }5 [1 O4 Hpublic:
; F6 x- `; }$ H8 e4 C& F virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }
! Y8 T+ z2 ]; M! o0 F2 Y8 o# L @ virtual bool CheckAndRefresh() { return false; }% F& x l$ p1 e- K5 }
virtual void StopAsyncFind() { }
( O* ~5 Z# F, f' |! L virtual void DeletePorts() { }1 V" ]9 {* G2 S" v8 x% n" {/ `' H
virtual bool IsReady() { return false; }
. A' ?0 y% |1 I' x virtual int GetImplementationID() { return UPNP_IMPL_NONE; }6 x$ X- ~' q. M4 A
};+ W( V: F$ m# _' j/ ]2 o& d8 B" I, }
+ t8 v7 q6 e/ i) y
5 j, J9 g* [/ n+ A: r' t& t8 V
/////////////////////////////////////
" k! Q3 W: o& T, ~* z. m B//下面是使用windows操作系统自带的UPNP功能的子类# ?4 u+ L, z1 L7 X2 _8 |
. C0 U C ?% g9 @2 U. G! b+ d' w! V" Y; z: ]( |9 @) Z# s8 f
#pragma once. s' ^ B! x1 c" S3 M
#pragma warning( disable: 4355 )
$ F: w0 p& ?) k, ?2 W# }, r3 R) Y; x! z: E0 U! O- ^' F- n
6 o( P# j5 j* `; g4 d& L#include "UPnPImpl.h", j3 ~1 l: Z7 z& {& g8 Y1 P
#include <upnp.h>: ^* k+ Z5 L: y. ~ V* s# ?3 Z
#include <iphlpapi.h>9 m7 [9 E9 w/ B0 U) `$ f3 o1 t
#include <comdef.h>
( y+ R9 r) r( n* M! M#include <winsvc.h>
9 |& {* P/ o/ E0 t' w+ |' [! \( E7 T2 T' W+ Z; b" t% O6 ]
L2 {6 l5 O& V8 t1 a
#include <vector>+ a: I& R) h1 N, N5 R% E2 c- q
#include <exception>; L" E: d4 z- z; K
#include <functional>
/ L4 e5 S3 x3 f$ Z2 ~: _- F- U1 A) K- `
! t. B) b- U# j% T% f$ \* _8 O& W$ X' Z2 M; T) ~" S* J' A+ E
0 n8 h4 B) F' b1 }8 C$ |
; d; ~# K4 Y7 W, _! L6 vtypedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;
1 V* ?6 C0 w5 m3 @typedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;
* |0 U4 ^8 l1 Dtypedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;2 X- N |( K v& y+ a9 B
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;( n# A6 X1 `3 P: O+ r
typedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;
9 E6 _4 X! a* W; Z0 V- \typedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;% D. V0 B1 q; }
typedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;
8 [6 r+ k @% f( f g
+ ?: T6 ]/ ^* B- F3 K
% b0 ~1 g; @4 R1 G6 D5 Ktypedef DWORD (WINAPI* TGetBestInterface) (
/ A4 @- ]. ?4 Z; h( J& { IPAddr dwDestAddr,
- E. P* c1 \! N8 B# ?; A. W e C* t PDWORD pdwBestIfIndex, m0 i/ q& N+ J' K3 S
);
; K! D" T3 U" \# j7 H$ q
1 ~) h, R( n9 e. p
8 p1 c* s% ?! v8 r. z& r2 R! Ttypedef DWORD (WINAPI* TGetIpAddrTable) (6 t# F& _/ `- b# l8 c4 c5 N
PMIB_IPADDRTABLE pIpAddrTable,
# a. ~2 @9 U5 B2 g5 x* v/ ~7 W PULONG pdwSize,
8 p6 O! \# r# k3 c, u BOOL bOrder. Y4 E2 P, W: w' i# E! F% e
);
; B- T8 `. N4 g" H
9 w N% p' E7 ?2 C# M2 @5 |& x
, H5 m1 a! O- r' \typedef DWORD (WINAPI* TGetIfEntry) (+ m# T. U; _) Z
PMIB_IFROW pIfRow$ j5 F) N: S# h! W! x6 [7 Y0 S
);
* S& X0 w* B- b/ L7 _& i
1 M1 Z9 w% b# h+ B9 K+ E) I7 t$ x7 o7 j( u8 y: {4 t, F& }
CString translateUPnPResult(HRESULT hr);
* P# Z4 c" b8 F( dHRESULT UPnPMessage(HRESULT hr);1 A) ]3 R4 p, B4 Z
, B9 A) m- a, L# b$ E) `
5 m- h5 i/ d$ Pclass CUPnPImplWinServ: public CUPnPImpl) i* l) u$ x6 _2 D! k g
{
9 P x& y, C1 }8 Q/ z friend class CDeviceFinderCallback;
Y- o' n$ S% b4 A- D: ? friend class CServiceCallback;
- H* a* G! ]" U" D$ p+ b// Construction
9 t5 l$ H; F' j5 J) ]) vpublic:) o1 H, a5 z: Y# Q, u8 f, [- C
virtual ~CUPnPImplWinServ();
; T, K3 A* F+ r8 V, r' c& i CUPnPImplWinServ();1 ~" K# S) ]5 f4 j
7 O7 }( a- {2 L2 l3 \& i0 o8 q. W" p$ X; E
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); } Z# e4 F9 p, k( m3 d, m
virtual void StopAsyncFind();
5 g1 L8 ~0 I5 a' f9 t virtual void DeletePorts();
, F$ p6 B) n1 u' U virtual bool IsReady();
1 V# e5 |. h. _- k# ` virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }
4 ]1 A* J$ g/ [0 ~7 l6 B! M1 W0 M- n! q
( q8 f( U' y" D' W, M: G
// No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc) O/ S6 u- ^! Z' d ~ d& {1 T
// the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later
+ L! n' {. T. X7 m virtual bool CheckAndRefresh() { return false; };. b) g( |5 B* D5 |0 w* O
, D; C6 C, q) w2 ~
. q) b7 _0 J7 ^protected:
# o1 R% t/ E8 d6 j void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);8 Q; z3 ~* M$ n, }9 A
void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);, k4 C# x% m; g, p3 z ?
void RemoveDevice(CComBSTR bsUDN);
( ]0 ]% L$ A. Z* q5 u: r l \ bool OnSearchComplete();- S9 j' U3 w5 ^
void Init();' E# l- v* c' x; R+ p" [
' U. ]" z. {/ \: S0 n3 X5 V( V. j/ S
inline bool IsAsyncFindRunning() A9 ]4 ?4 _3 W
{
# f: V, {8 z7 O+ }( S: q7 t# P if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )
' h5 J8 l$ `, l# O3 u8 a7 [ {3 I( S9 \7 F7 C+ D( w" `5 T# o. g# ~
m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );
( u1 p6 O1 n' U. E: c) w m_bAsyncFindRunning = false;4 U' \( S; u; r) v6 a# y
}
8 ?$ }1 M$ }+ J MSG msg;
3 m7 u5 Y) R. `% u5 H+ K8 G7 Z while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )0 }" W$ M- D8 X* w; O$ X j; N+ R( b
{
: _/ \$ k2 q1 W- ]% M8 H TranslateMessage( &msg );
5 o* x$ y5 ]/ C5 m DispatchMessage( &msg );
+ Q( f: v3 u5 M( T }
5 g9 Q- h3 i: S# j; a/ ~ return m_bAsyncFindRunning;
" |6 g7 A/ y! X9 e4 T }
0 @( B! [, E( t* g; x5 S3 _( S3 |/ B2 }( u& {8 m
" @! o$ R9 ]7 P2 c3 i( L' K% q TRISTATE m_bUPnPDeviceConnected;, m+ C$ [/ H5 b3 r+ y# V% V {* W
- H3 x( |# p' I3 k
) N. q+ f' `" W- c$ K
// Implementation
8 g5 x* n( q7 I& x, q' W // API functions6 B# `( u+ Q. U! }! u
SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);2 Z$ S% z& B" r8 N( p
SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);
! F" n5 d. n/ P+ }3 Z' J BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);
$ Y$ D1 q9 @$ y+ D BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);# \" D* y5 `7 m& _) B
BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);
+ u, O; f5 W( |$ X& Q BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);
- f+ s* i8 V4 f- `7 {+ D" y3 E
; f& _0 {/ N3 A6 p T) W) R: L# _' L$ ^4 ?9 p6 A4 D& s
TGetBestInterface m_pfGetBestInterface;
! `5 u0 I) `0 ~3 E8 ^) l7 G TGetIpAddrTable m_pfGetIpAddrTable;
" r9 F1 U( X7 G4 ]% p3 B4 Q: [+ | TGetIfEntry m_pfGetIfEntry;7 N! n" }$ ]; [5 U8 q, i
% z# V9 d( ]; A% o; j* v/ D# u
% U9 N( E% b, J+ f# @ static FinderPointer CreateFinderInstance();! J3 {& {1 L4 i
struct FindDevice : std::unary_function< DevicePointer, bool >5 A+ c* W' z0 N$ a/ {
{
. `& ~; O. C# W V% H+ Y FindDevice(const CComBSTR& udn) : m_udn( udn ) {}
# g5 H* f; O- V6 J result_type operator()(argument_type device) const% Y. Y4 h. y& U
{4 a. H& H. \0 q( I' x
CComBSTR deviceName;
3 Q* k; n1 D+ t4 w5 ? HRESULT hr = device->get_UniqueDeviceName( &deviceName );
- V4 ]! r+ O1 `3 E! R) _& R
! }. |+ [$ C3 x- s! t0 L
$ y0 a+ c' r9 L) v7 ] if ( FAILED( hr ) )( y, J1 _8 g' I" H3 ^8 k0 \1 W0 x
return UPnPMessage( hr ), false;% J2 `' b+ M8 a. @
$ i; [. v; z- [; ^
+ V2 e; b( a) Y E3 ?$ k return wcscmp( deviceName.m_str, m_udn ) == 0;3 F0 W6 c0 ~& u3 ~/ n
}3 p2 @6 t: ^3 [
CComBSTR m_udn;, N, P$ z/ @ \0 |# T
};
2 A8 c: i0 v" G! _' u3 B
3 K1 X+ Q0 u/ ], I. T void ProcessAsyncFind(CComBSTR bsSearchType);1 `: `, S" s! ^ h
HRESULT GetDeviceServices(DevicePointer pDevice);
- ]6 M% x1 H0 L, y9 ] void StartPortMapping();! b. }0 G/ O. m7 r
HRESULT MapPort(const ServicePointer& service);0 F1 J; O& l' f/ B1 O& t
void DeleteExistingPortMappings(ServicePointer pService);
# d3 i, |, i* [" O& k void CreatePortMappings(ServicePointer pService);
$ E: f( n0 ~. }% k; H. m1 f, C HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);
( q4 F6 S* D) U, Y4 ]- Y HRESULT InvokeAction(ServicePointer pService, CComBSTR action, 7 I0 t, A( Q3 a/ t& c' {
LPCTSTR pszInArgString, CString& strResult);
8 I/ Q$ m! y1 J6 n void StopUPnPService();
1 L5 B0 Y" M0 @0 ^8 D! r% G) T3 N( U& G2 y+ G0 R' I+ e; |9 U1 F
' ~' h$ e$ p- Y$ h5 B) e // Utility functions" D; Z- W' s l& f. O( M
HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);2 s5 X& Z. R9 Y
INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);) ?& ^ L* u! d: R. F
INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);& |) }% O) z% F. G3 v
void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);
) k& R( o9 u, D# I HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);
2 w0 P2 \" A: c/ {- s* ^- x. z& P% j HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);: y* }, |, I: _3 _
CString GetLocalRoutableIP(ServicePointer pService);* d, R7 x5 g: ~4 V8 G
; f0 |+ M9 l0 T; J' {, T: L; s M W
// Private members0 X2 a& R* L, s: G) W$ y' a$ z
private:
& p7 P( k9 M" Y DWORD m_tLastEvent; // When the last event was received?
0 j2 j+ K' S6 I+ H. _* x std::vector< DevicePointer > m_pDevices;
- O' F8 W- ]3 I. {7 c0 z& `) m std::vector< ServicePointer > m_pServices;( E4 u9 V% u0 y; S9 B
FinderPointer m_pDeviceFinder;
# l, z" k- y! V6 c DeviceFinderCallback m_pDeviceFinderCallback;
4 n. l, ~4 _5 `& E5 Z0 e5 T ServiceCallback m_pServiceCallback;" J+ H* f( w# C* t: @; Y( {
5 J( A/ B) ^& ?8 }* o8 n3 @4 k. l- m
LONG m_nAsyncFindHandle;8 o. T# P; Q! k, ^* S4 {5 h
bool m_bCOM;
. a/ k6 o! {# \1 M/ R& f: b1 t bool m_bPortIsFree;; `, a5 X3 ` q7 \/ d
CString m_sLocalIP;. D: _/ l; z9 r7 E/ f
CString m_sExternalIP;
9 D7 f& a* c0 ` bool m_bADSL; // Is the device ADSL?
4 s& e& S# m6 h7 p. O U$ K bool m_ADSLFailed; // Did port mapping failed for the ADSL device?2 W1 p% m* B$ ~. E% J
bool m_bInited;
/ y5 k; i. p& x8 |4 y* i$ ?" |( l' h3 Q bool m_bAsyncFindRunning;
/ w+ I: ^: O% O6 C$ ] HMODULE m_hADVAPI32_DLL;
8 {* I/ q. I! E5 h2 \$ I q HMODULE m_hIPHLPAPI_DLL;' l) o) `5 S, [; v! z9 r
bool m_bSecondTry;
/ r. S$ F$ p+ c; `. V( s2 {1 g u. j bool m_bServiceStartedByEmule;
6 S5 U, z# A' M* S+ e6 u M2 e bool m_bDisableWANIPSetup;
: S0 W/ a, h% u. X5 f bool m_bDisableWANPPPSetup;
+ L' h' g3 a a+ L2 v' n" B+ B/ @! z9 v
7 B/ z- O" ^9 b) R2 ?}; x8 N% t- }( \# I6 Z: ?3 E
- r( Y. F& v2 I& e0 k' j
) t: {) r8 ]7 N" D// DeviceFinder Callback B4 |1 @/ G$ x, e
class CDeviceFinderCallback
* N4 U: V9 c4 } : public IUPnPDeviceFinderCallback
4 K; o# j1 G' p) H{
! S' ]% x* Z0 l2 M( Mpublic:
. s/ F3 Y4 g; G; P) v CDeviceFinderCallback(CUPnPImplWinServ& instance)
* g7 P8 j, W6 }* C1 R! k" p- p, H : m_instance( instance )$ B7 V+ D' `' s+ U2 M7 A
{ m_lRefCount = 0; }
2 P$ k1 r: V. L$ b/ g4 I
, u4 r* i/ Y/ B4 m9 q. x- `. m3 a" Y6 [
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);0 U- N- z: `. _1 g* D
STDMETHODIMP_(ULONG) AddRef();
/ h4 o% C1 z* V/ e1 u STDMETHODIMP_(ULONG) Release();
- g8 c" s/ ]$ ?" J" t, _+ ?7 j- k1 y6 j3 k
h( P. G. B f# T% E// implementation) k8 }% O m, j% ]
private:8 |( l) p0 P! E1 S5 ]$ n' K
HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);$ x& K3 r6 i h* E7 c% w
HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);
4 x5 |+ k1 y5 ] E HRESULT __stdcall SearchComplete(LONG nFindData);# X. }, f' K; q$ U: t' D4 ]
4 F" W+ }7 N& R
& _/ x9 x0 j3 S, H4 C
private:# A5 n) S* l0 u: A( B \! }
CUPnPImplWinServ& m_instance;
# Q# p# i* F7 _% u! i0 X4 X LONG m_lRefCount;6 h5 q# C7 d2 s8 d4 W B0 n
};
4 b% [- L; l$ z' {7 t( Q& Z# r1 J. S; y5 W/ G. F
4 @$ P0 d: U* w1 j, {$ [0 R. D// Service Callback
4 { Y. f% L0 s _& ?" ~class CServiceCallback
2 P; O$ v. I7 z6 w8 s3 A _ : public IUPnPServiceCallback
( J. q9 e2 z( X& ]+ _! \) G# |{
, u4 g9 b; b, p( w8 R0 ?5 @6 }- wpublic:
7 f$ |# N( Q- N9 w- Z4 P) N+ k+ [ CServiceCallback(CUPnPImplWinServ& instance)
$ M5 @ ]( K& s: [' p; t. | : m_instance( instance )7 p3 K# B! }3 \& C# n
{ m_lRefCount = 0; }
& f3 z3 `2 S" E Z: A7 Q+ \
5 Z7 s: A5 J! N STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
/ v5 V- x$ [4 f5 L: W6 v STDMETHODIMP_(ULONG) AddRef();
& c- |6 D1 b4 b6 ^4 k STDMETHODIMP_(ULONG) Release();
, O1 Y6 n6 d3 i8 s k2 ^0 o$ Q3 v, i6 C# ~
% l7 G! P2 n5 [4 Z+ p% j
// implementation
& z- k; D: G+ Q( k( E1 Q1 [private:
8 C7 u( d# ?2 E9 G- \ HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);
& m# d& ~; x. P+ u+ v HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);3 v$ ~0 D: z4 ?; |
) N# y! {# r) t% _
" T4 x5 {$ V- h+ c- |private:( \' z- U) i; e3 a
CUPnPImplWinServ& m_instance;
1 [& P0 P& L5 W: a LONG m_lRefCount;* d. [+ z2 z; w; l* K
};+ a+ J5 C0 c. a9 s1 r. @( R
3 ~0 @* t& l4 c3 v7 o) x
4 g& T7 `& I' b) O$ L/////////////////////////////////////////////////- ]- B6 C3 j6 y. ]
( h: o) ^& a- n$ }* f) W
3 b8 V0 h: h; Y$ c) t8 w
使用时只需要使用抽象类的接口。
7 K) Z2 x2 _9 u4 l4 `: KCUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.
: g& ]+ ~0 v0 c1 w4 M: DCUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.
9 s% \2 J% n' B- m8 ~5 FCUPnPImpl::StopAsyncFind停止设备查找.* b& R; \# a6 B* z1 [
CUPnPImpl::DeletePorts删除端口映射. |
|