|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule," z' j: c; X5 q: }; `
4 w6 g* d; H1 {6 X$ v1 C' C
( ?* h3 S+ [; ]# K' |/ z+ b
///////////////////////////////////////////6 w* [* B/ F. J, B5 d
//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.5 a+ a0 j7 c6 G* P4 Z" B4 j- a
4 G, u; X% L( [0 K$ ^& O8 I+ ^
7 ?8 q, X) [6 W8 L a
#pragma once3 ]5 [! o' Z( J# e
#include <exception>
7 w# r. U% a% b# v4 i( R( K; b5 h; L( O; ]- G
3 A m, |1 y! i enum TRISTATE{1 a# B/ A! q( \! Q" h7 M
TRIS_FALSE,
4 D0 I7 c: V: V. m' f) N2 o TRIS_UNKNOWN,
; C$ i0 f y7 z TRIS_TRUE
" Q8 A! r/ q6 r! P" T/ ?/ W0 a1 N}; u. |6 I) q" h2 v
9 T* m0 Z3 e3 _% v+ H
" N% [- n- @& l+ N+ nenum UPNP_IMPLEMENTATION{
]' c$ P, [9 Q p9 O1 N UPNP_IMPL_WINDOWSERVICE = 0,& u9 z( s. O# X& M" R8 r- [
UPNP_IMPL_MINIUPNPLIB,. M9 D6 d# O0 P2 g$ b3 ~1 I
UPNP_IMPL_NONE /*last*/
. \7 C( m1 t+ \6 j};
( ?! n) W! m, _6 f# f" {; a) B+ D# D1 F
0 M' \7 K @$ O
) ]( B" E1 D6 b
" S: }8 D1 O% a; U: |/ T. u/ T
class CUPnPImpl
3 }1 e% m: X( z) `" h# `/ c{
3 c2 T' [$ J! u% d% {$ h# I: x. xpublic:1 i3 B3 R* U* x% j8 T) d: E# k
CUPnPImpl();- x$ B- T( M5 `; ]. [+ G! @
virtual ~CUPnPImpl();. M7 }4 F2 s+ E: t
struct UPnPError : std::exception {};" w' B# Z; j! L; y
enum {' H/ e0 u. h# k. c2 O L9 u9 c
UPNP_OK,
0 [$ z' l& U, v9 H, D+ | UPNP_FAILED,
: V7 j( k' l- \. t UPNP_TIMEOUT9 P( o2 B8 k- E, N, l
};2 `: z& {% \3 K) k
" B) ^( X" R+ `( E
; `$ n5 t7 v' M' H4 Y5 i virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;
( I2 r- B( K O# ` virtual bool CheckAndRefresh() = 0;# [7 _1 L- I4 R3 B% b$ u2 G
virtual void StopAsyncFind() = 0;
# X' Z, U# g/ }1 c1 G virtual void DeletePorts() = 0;
7 n+ j6 `0 @1 y& H virtual bool IsReady() = 0;0 M E& o# Y+ G- ^% _
virtual int GetImplementationID() = 0;
t) N+ J* \" Y& c! k1 j
# K' [7 n% Q$ W; s; X3 K: z void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping, l2 C) P) Z* d4 t2 K, U7 Z
$ Y! \) a. v# u( ?0 B' l( d" L& F! f5 \
void SetMessageOnResult(HWND hWindow, UINT nMessageID);
( I- [: Z# i4 q* v) L TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }
/ D$ x- J& i9 i) V- |- x ? uint16 GetUsedTCPPort() { return m_nTCPPort; }: m( s6 w& e$ {3 Y' l1 D
uint16 GetUsedUDPPort() { return m_nUDPPort; }
8 R% `# j& o t. e5 U' v* u7 j
& P9 L8 m, E2 A* Q
: d. R$ f7 Y$ g9 |# r- y, T// Implementation& J, q' N. s [8 l, k
protected:
* g. z" y/ O P' B) \ volatile TRISTATE m_bUPnPPortsForwarded;
: E& V0 W: A7 r& ?" k: `( y' r void SendResultMessage();
: J! B1 c8 E- D4 [( T uint16 m_nUDPPort;
; \! K6 P0 T9 A3 ?1 d+ _ uint16 m_nTCPPort;
6 l; M$ w. i; K; X0 n uint16 m_nTCPWebPort;
7 `3 C" M6 l4 c2 T bool m_bCheckAndRefresh;
% b, q9 H- o2 }. q, X; ]+ R" g
6 ]0 M2 A+ N9 d) l' f) u) j2 k c/ e7 ?& n
private:# W, \, N6 V$ _( g
HWND m_hResultMessageWindow;
1 @- f$ u1 G+ [; t+ [ UINT m_nResultMessageID;! f& n5 m( h9 M v, C
' F! V( E8 |9 M7 n3 m/ \
$ q3 m+ \9 L$ D! ^/ d6 l) j
};2 J, l5 o9 R( t/ r3 C. }
- `! }4 D! ?, E! E- C
; ]0 x' a( ?2 D# x' e! P9 i
// Dummy Implementation to be used when no other implementation is available
2 r. Y7 N1 E+ _class CUPnPImplNone: public CUPnPImpl( E3 b5 E1 F; i; y) S
{
" c' t9 o, L7 K- q9 K5 Dpublic:
* `$ C" p9 ]7 V9 g) f g) e virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }8 |* v+ p o3 b
virtual bool CheckAndRefresh() { return false; }- R1 T7 x4 c: H! p9 M* w
virtual void StopAsyncFind() { }: y, a( _" O' ]8 ~8 k4 z& |
virtual void DeletePorts() { }
( J+ n1 }% i# ?0 }# ? virtual bool IsReady() { return false; }
$ V9 `5 r4 @2 _4 w virtual int GetImplementationID() { return UPNP_IMPL_NONE; }
. E1 _5 b; Z4 e, d) M8 l0 Q2 y};
/ R4 n4 y: m. r& ~3 z5 Q& P: O4 a7 Q0 g) g! a
& F' G3 ]1 j1 I& g _/////////////////////////////////////* j. G. s2 t ]2 A& c2 B+ i9 H8 j/ [- u
//下面是使用windows操作系统自带的UPNP功能的子类. i0 @: \* V/ O6 b) E0 l. Y) V
! J4 ] x: y# r5 Y# n3 s" ~& ~5 c3 a L9 f3 ^! h6 D$ ^5 @& p9 K
#pragma once& ~% F- V- d/ b, y+ d9 ?5 o! d
#pragma warning( disable: 4355 )! |9 b) X/ b4 [" _: ~
* f& V' A$ G3 a. Q0 ~: K! f, r, l( n5 Y2 k5 I
#include "UPnPImpl.h"
( I: G- g* j, x9 G) H1 G#include <upnp.h>
0 w0 I: Q7 g6 {( V#include <iphlpapi.h>' ~/ e/ c5 W: W( a
#include <comdef.h>
8 U/ P& I; b/ i#include <winsvc.h>4 d9 B: \; g I: Y( ^, h, B
$ _/ P6 c" g2 j! P8 M/ F
- I5 l' C. p; c' R' H9 i' a: U#include <vector>
5 B \2 g. t* P#include <exception>5 I1 l& L7 i1 }: f
#include <functional>
4 J7 D( Q" |4 g; `+ C' `; H, R& V1 v" ^- r$ I7 G7 e
9 j! v1 X: F/ ]! Q7 T- ]3 }" }
; _# S- I7 T, d6 s9 H: T- O4 y" x: F4 U i
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;& h( R# p( t* O" j
typedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;/ [, k% j3 o0 ?: R
typedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;9 I$ ~6 t1 N" z6 a* g: V
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;# \ I. q1 D5 G( C! i: K) a" ^
typedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;
6 r5 w1 ]) v1 j7 ^8 H( [4 ?typedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;
' w2 {5 w' V" Rtypedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;
- @. W9 Q& i. g1 H4 ~1 x1 v! T# \' h) P4 g2 L
' w" t; d+ y) N% d
typedef DWORD (WINAPI* TGetBestInterface) (+ A2 y, `& g+ j6 d7 i$ S8 c% ^
IPAddr dwDestAddr,8 ?1 d8 G ?) c/ E" |
PDWORD pdwBestIfIndex
+ ^) B }$ p+ x3 u);5 ]+ q7 i' M6 _
% n7 Y" d! w8 M2 m5 Z
. j* s$ o: {# G q/ Ftypedef DWORD (WINAPI* TGetIpAddrTable) (9 F- U" T0 \3 }) s) Y7 x
PMIB_IPADDRTABLE pIpAddrTable,: n# B, X; h3 k- f" }
PULONG pdwSize,; d* n3 G" d, H T5 A7 V1 F( a
BOOL bOrder/ d$ z) w8 C U) l" z6 n7 K
);: j4 ~! n8 u0 ~
7 l9 z+ z" Q. ?6 Q- U& m9 b
) I" F% G% ~; E% C0 a
typedef DWORD (WINAPI* TGetIfEntry) (1 a: _5 S+ W1 ~
PMIB_IFROW pIfRow3 F+ s5 n5 p; w8 |" E/ V! P
);- K( `$ m/ q" @) O1 a
x* l8 Q2 V0 w, Z
! g6 R5 }# n) r( ~CString translateUPnPResult(HRESULT hr);# q1 F: L; {3 [
HRESULT UPnPMessage(HRESULT hr);
9 ^) I( R: M2 ]$ s
. l7 e+ \$ E. Y" }8 k- J! u; l H2 x
class CUPnPImplWinServ: public CUPnPImpl
4 ?$ q, |# r0 k% e% t{
8 |: K+ |8 D2 J' X# |9 J friend class CDeviceFinderCallback;
& U; e8 U3 a! J# e1 }) k friend class CServiceCallback;( d6 x$ P$ x5 Y9 a( {) P
// Construction
: j& }5 V: ?5 Spublic:
( c4 j# U3 f% Z virtual ~CUPnPImplWinServ();
% I, [5 h% R& O, t CUPnPImplWinServ();- y! o, h) ?$ c& j/ r. b
: e, o( `1 h! N2 p& \( k/ p
9 |! E f% L* Z9 P' w virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }
* J( z, |. b, N7 d+ n- g virtual void StopAsyncFind();% U" }. v2 Y: s8 o
virtual void DeletePorts();
4 O" Y; {$ a Q$ X virtual bool IsReady();0 G5 F2 L9 g* d5 ~& Y
virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }
! U$ H( _2 G* g5 r' W- S$ W+ T
( _$ J" l$ w) ~9 b
// No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)3 ]% v5 N! M! v6 P$ S+ I
// the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later
g( j/ Q) f% j/ D6 R s. k3 ] virtual bool CheckAndRefresh() { return false; };0 y) ^0 p/ T+ ~8 l
+ ?" l; W* K0 N' w y
5 X# H2 X, _# L% z M& X: Q$ Y3 C) Fprotected:
b; K! N4 ^% B$ ]: W. T void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);! K e+ G0 k/ y8 n/ l
void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0); Z" r' k& q* o( y+ E' ~5 v
void RemoveDevice(CComBSTR bsUDN);* ^7 h7 @# e. F) u* Q, Q& X
bool OnSearchComplete();
5 b! {- y& u9 ]. j void Init();4 Y3 X9 r# m" i2 w" Y5 c9 D( ?& X
1 v0 y2 J9 I6 i& T; n8 `
9 l6 b% A1 O8 g$ d _ inline bool IsAsyncFindRunning()
: T& S& ~: t4 b# f) }' ~ {
0 q- D8 _2 S K9 H6 v+ F1 { if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )
- T6 d1 Z! X8 P& W5 R u5 m6 [0 k$ U {" H: q4 D4 Q! z C* \& b
m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );9 t" A* L' _4 s% L- P9 @
m_bAsyncFindRunning = false;3 }2 c# I/ T! w7 G% W
}2 o2 V% A/ P1 ~! G/ `7 |$ K8 u
MSG msg;
7 y7 ]6 o4 E3 e; Y4 m- I$ Q, S6 y while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
2 v/ J f6 A8 P) ?& `4 ? {' R2 F+ f9 g9 S% n
TranslateMessage( &msg );
5 w5 R$ W. }! p: O' @4 v+ c DispatchMessage( &msg );3 z% [8 {5 _2 E1 k, q3 z9 g# R. H
}0 T7 Z. q1 B2 a, Q$ e
return m_bAsyncFindRunning;# N- ~& A* r; }( l. T
}6 u4 r( N5 |9 \8 ?6 w# ]' `9 ]
& h" n5 R' C* \
3 O1 C) x- K: t$ t
TRISTATE m_bUPnPDeviceConnected;% e' o7 A# k9 P
" l6 i" F2 R: l+ b+ v) @" E$ n+ p$ q0 t$ h) F
// Implementation6 N$ t, U7 z4 @- m/ ]
// API functions T' [6 S9 f3 p! d
SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);
% \$ F7 l8 A# G9 c0 J SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);& h0 L& o# l& E/ P
BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);" E" H: P. V$ M* |3 X8 K
BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);
# T% p t& H7 ^ i' V BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);- D4 X# T/ h) H3 k- ~% C1 V
BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);
% y- d6 `1 F \8 Q& d' H# l. h# r4 X% w7 G. b( U6 p' Y, D
5 \/ H# D2 ?$ M& B/ i7 k TGetBestInterface m_pfGetBestInterface;* d; V, y, H, {& l0 L/ G+ q
TGetIpAddrTable m_pfGetIpAddrTable;* ^/ W/ }7 G: d" ^. d
TGetIfEntry m_pfGetIfEntry;( ~* i5 Z; \" a6 T. _8 K; M
# Q/ L; E0 Y. c1 ?2 f% s) R+ @0 Q
5 p H( c8 Z2 N0 t4 e+ l, r% [
static FinderPointer CreateFinderInstance();* S) J5 t V4 K
struct FindDevice : std::unary_function< DevicePointer, bool >3 H* K1 g: G- X
{$ \) E& B$ H) d
FindDevice(const CComBSTR& udn) : m_udn( udn ) {}! |1 ^: T- C/ U q+ q# p% D3 z! {* P
result_type operator()(argument_type device) const! K" ~$ _+ s' m1 U5 B+ B8 Q7 j; c
{* ?5 C7 x2 }% ^6 p! b
CComBSTR deviceName;( i) F$ q2 a6 w% `
HRESULT hr = device->get_UniqueDeviceName( &deviceName );
7 p! Y* g% S% C. X* S9 ?; b& t, p
" W7 ]( V/ v; e) x t2 r$ _9 l4 X
- b& |$ }2 T9 q& `2 j; X if ( FAILED( hr ) )
2 K2 [5 M! M6 }" B+ k return UPnPMessage( hr ), false;9 I/ j; l) a: i. Q# B5 `
* G+ `2 L- F7 x+ H) s3 r# Q) N! k
% k' `9 {* A h return wcscmp( deviceName.m_str, m_udn ) == 0;5 ]4 s0 H* W! `) o6 Y2 Y. }. I
}! h8 t- |0 {+ [" S2 z$ A# X
CComBSTR m_udn;, c5 ?4 T. r9 }8 Z2 L& v
};
* n, \9 Q8 v& J+ o$ W7 s5 Q ! J8 P- N" ?! @! A) u: d
void ProcessAsyncFind(CComBSTR bsSearchType);
0 k' `( H% w6 b0 d; [& _, Z) {# Z HRESULT GetDeviceServices(DevicePointer pDevice);
2 X4 i) y/ U3 u7 s Q void StartPortMapping();4 j, K8 e& C' ]( B% v+ W3 Y
HRESULT MapPort(const ServicePointer& service);
U+ c. G' S1 z3 I/ g9 k void DeleteExistingPortMappings(ServicePointer pService);
$ m6 O- M3 y# w void CreatePortMappings(ServicePointer pService);
) t3 c* o3 y- l/ L HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);
" ~+ K3 V5 J( z% B. ` HRESULT InvokeAction(ServicePointer pService, CComBSTR action,
# `5 Q$ C$ [9 N* p/ F4 C0 j LPCTSTR pszInArgString, CString& strResult);
: f" M3 N7 s4 z7 Y# u4 Z$ h; H void StopUPnPService();' r! I- y! O4 A; l& R; q' Z, }8 h
* L; s+ _$ I' n7 m* J s
9 b* B7 x- r* J1 H0 ?! O( ] // Utility functions) g, w# N7 S7 l; B
HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);$ m* R& f4 e# a; }7 }' a! X
INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);
: q+ M, U0 }' Y+ t4 ], ] INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);
. S* I) I, y n void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);# }, J1 j9 D9 c: \2 u( w! i
HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);
4 |. W% f3 _. X, p% q HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);
4 n6 ]3 K' v3 T8 {! k# N CString GetLocalRoutableIP(ServicePointer pService);
, |6 d' T: A' G$ A/ J
( e9 V) |+ z! t9 U# l
( K; m( d: |- T2 m$ _: e; t// Private members7 w* U6 d2 \$ d/ n( ^( v
private:
* H3 C7 O4 h6 {0 \0 @/ M: y DWORD m_tLastEvent; // When the last event was received?
) S5 S m: T$ x( {9 d% p* t; n! u std::vector< DevicePointer > m_pDevices;
. b) A8 \3 D9 _) R std::vector< ServicePointer > m_pServices;
# c% J1 ]. @" ` FinderPointer m_pDeviceFinder;4 Q4 K( u3 J" f) z
DeviceFinderCallback m_pDeviceFinderCallback;2 z9 C$ }( c) v
ServiceCallback m_pServiceCallback;
- Z4 j' [' ]1 H
* O; ~: Y. w! T2 M W
5 G9 G s B# Y% O7 O- ~ LONG m_nAsyncFindHandle;* e) `) e8 h" b
bool m_bCOM;
$ g9 E% n3 m+ i% C( c/ C bool m_bPortIsFree;
9 D! m0 b! h4 N0 D CString m_sLocalIP;! D+ I& @5 `4 `8 R& h. g m; T
CString m_sExternalIP;
8 H: t. |5 a& G bool m_bADSL; // Is the device ADSL?
4 O" @2 S6 f H9 G. e bool m_ADSLFailed; // Did port mapping failed for the ADSL device?+ `9 ]: M" c! e6 Q
bool m_bInited;
% d: c" ?+ W& I; K) C3 a& z- K bool m_bAsyncFindRunning;5 o3 D+ n& w$ T& x4 ?
HMODULE m_hADVAPI32_DLL;
! H6 B8 O" `3 n0 P8 E: Q HMODULE m_hIPHLPAPI_DLL;; A# e& F/ t* f8 K; s
bool m_bSecondTry;1 M4 a" z. T/ \# j; H& B/ l
bool m_bServiceStartedByEmule;
7 r3 L2 |" o* V- h2 [$ {/ d bool m_bDisableWANIPSetup; f O* g, C6 f9 O
bool m_bDisableWANPPPSetup;! {4 `" c. t% H9 b0 {, E+ A0 Z
$ @) R9 N8 V; P
* P1 J1 r4 F! K8 F4 t) V) H9 Z% |
};! w7 S5 S9 b$ k* d! Z& Z( B
, d# O0 V4 ]+ l% K5 r3 E0 L& E
+ \: m, ^. I$ C3 w; b& C// DeviceFinder Callback0 A, m" M$ }% ^! A* g$ P" L
class CDeviceFinderCallback( I8 K( D& m# K+ O2 o, T3 Q4 W
: public IUPnPDeviceFinderCallback: ?# y2 @3 S- @% p( Q$ _1 W+ U
{
1 F5 r Q; r2 ^, V! N3 ^public:- s# E( T# Y+ h
CDeviceFinderCallback(CUPnPImplWinServ& instance)/ _' a0 m+ D( P; T' O6 @
: m_instance( instance )
) m8 N% F& Q( \0 S7 y { m_lRefCount = 0; }
( f! Y* o. b% I3 X# E# Z" a
, w8 R' e! o1 g: y- l+ s& H. T
. J3 N( }0 c+ ~, M! |7 j' R6 C STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
, T4 Q i8 h0 p, ^ STDMETHODIMP_(ULONG) AddRef();3 B l9 a# p5 B9 F2 t7 O3 ^! _% M
STDMETHODIMP_(ULONG) Release();
1 b$ N( i, T% a* |# F" \
0 E5 h7 s/ k9 J7 n& X. P
# A* D6 i) w3 G: i; F& l// implementation- C$ b5 [, O: O6 Z7 o6 d
private:
1 G& s' G, E) W: a$ H: @' S2 |# a HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);
. {- O! t: c& {; t _1 m5 { HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);
% R+ [( I1 F( Y: b5 f+ u+ X1 e HRESULT __stdcall SearchComplete(LONG nFindData);
( n/ p, d$ q7 [5 O( R7 v6 r$ ^# y0 n8 k. X: {! Z0 |; \- F$ a3 B
7 @! m' o9 g! [# _
private:& J) G7 F1 A8 Z" C0 E1 W4 E0 H) W
CUPnPImplWinServ& m_instance;! k8 p# [ o' s6 {7 ~& ^+ m
LONG m_lRefCount;! c2 |$ ^+ `+ C1 y
};
. h; j! L+ U, e: n- x+ W6 O2 |* I2 P) o' v6 A, c; g% r
2 j, H2 K5 b3 J9 [0 T
// Service Callback k5 d6 y: g% V8 T% Z
class CServiceCallback+ S) k0 M* m7 o- ]) J3 w
: public IUPnPServiceCallback" D; G+ Z! O# P8 e! A
{* i! T( E& \2 r- a" s/ X( l& I: j1 P
public:/ {/ h* g9 H D
CServiceCallback(CUPnPImplWinServ& instance)
% _0 U+ ~6 o$ o- S5 J* Y& m1 r : m_instance( instance )
9 t# h) H/ U8 S5 Z! M4 ^ { m_lRefCount = 0; }! u0 }5 y% z$ ~' W+ F0 @
6 A( o. V/ X* J5 q5 S. f; ]" Q1 p
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
- F6 ? a; v: ?& z& p: [ STDMETHODIMP_(ULONG) AddRef();& Z0 N. @1 C" X Y! Y
STDMETHODIMP_(ULONG) Release();
) h5 n1 H ]! H# c. [3 f, R& r/ d$ c
- f/ Y, j) g' `8 W+ s
// implementation9 e |! A, H1 _1 B3 F3 B( D
private:; J+ }7 Q/ Y1 n6 U) V
HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);5 O1 v7 z" ]! C
HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);- W/ w) P! _( I L+ E$ r$ v
. B$ `1 b; X- j4 o
, P7 v. z1 `5 \5 c- G, F( @
private:
2 b: F3 b. e/ j w3 W CUPnPImplWinServ& m_instance;4 R% A% q X' H; M
LONG m_lRefCount;
8 S8 }; r( e5 D/ N/ I' {( T};
2 O. C* w; q0 Y5 @3 b$ e3 R& s# Q
2 Y3 i" m# _6 o
5 g0 x. X3 @8 D e/////////////////////////////////////////////////- C2 d O0 @$ V7 y2 N6 q
p" X+ F' L" m* n/ K( X$ o2 y7 B
8 ~0 Y; o9 E* q2 Q
使用时只需要使用抽象类的接口。$ k6 _6 u4 u, y! Q( U
CUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.
( t+ k* d1 M6 S. \& SCUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口. @ Q. k5 v+ ?7 |& P: S" K
CUPnPImpl::StopAsyncFind停止设备查找.
2 k+ S7 u2 Y1 Z7 J8 {CUPnPImpl::DeletePorts删除端口映射. |
|