|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule,( [8 |( U6 t \4 p' Q
: s1 H1 F! o: s2 ^# e; Z1 u7 ~
$ i/ o, {; z9 J///////////////////////////////////////////: y: t( ?: K4 J# X: O8 x H
//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.; a: R0 ]2 q" W; F: ~1 Q
8 N4 U: z3 D. J; }
5 l# X$ \# h% E7 b$ `2 B
#pragma once; z0 s+ M. d) c
#include <exception>
9 w5 }% o- T; R* R* C+ [ s3 a9 v) ^2 c4 @
" }/ _( ?/ R3 R* h) R enum TRISTATE{# f ^( \% j2 s9 D8 f4 {# e c
TRIS_FALSE,
0 E% Z/ X r: T9 l: B2 _; R TRIS_UNKNOWN,5 p; x X# P' t: q4 v; s9 l$ k
TRIS_TRUE
7 @( u1 q4 n: \# X2 P};
, A" i! K0 R) p7 O4 G4 R, A0 C; \& E
6 `. b1 |1 _9 |* p/ c
enum UPNP_IMPLEMENTATION{8 v& Y! Q8 a2 p) l, ]4 [
UPNP_IMPL_WINDOWSERVICE = 0,8 `1 ^9 i6 n1 M2 \" o
UPNP_IMPL_MINIUPNPLIB," i- Y( e3 @- E4 X, L1 v/ E
UPNP_IMPL_NONE /*last*/) P' a* F. X# t9 C: _
};
: p6 e" A. X; h% J! u, K3 C/ D9 G, W: x9 z1 V6 p- I9 p: M
) K$ F7 u- K+ d$ j8 t8 c2 |% k* a
" p' G# \! k( c0 ^4 @
- Y" Y# c( D1 {+ d% [class CUPnPImpl; \4 e+ U4 r* X
{6 M* n/ c+ l4 @0 W5 ]
public:; s! ^% b+ h! m9 ]1 l
CUPnPImpl();
- b( E$ P. E" r virtual ~CUPnPImpl();
' V8 B" {( l6 M struct UPnPError : std::exception {};
6 O4 E9 S$ I# J6 [% f9 B! A" t enum {( v9 D% l; V- j1 `2 x& @
UPNP_OK,
& [- ~' {" U V' m5 {7 S UPNP_FAILED,: @5 E( d8 a U& ^+ @* C
UPNP_TIMEOUT
( ~0 c. O- s" S& E };
. `3 x" }2 J' p6 _6 F9 {, K; D7 M7 ~% u, K2 ]6 }- ] p, j
1 W, |+ ]2 W7 }
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;
# \' z4 V7 y& ]! O( s# _" P virtual bool CheckAndRefresh() = 0; X q, u. M( \+ L0 W1 g6 n5 ]) i
virtual void StopAsyncFind() = 0;
# `' L9 E1 G: }. A- @, ]4 @ virtual void DeletePorts() = 0;4 ^, M9 g) g0 R' d) T$ t. ?3 {$ g
virtual bool IsReady() = 0;) d! }# b# [9 y. T( L
virtual int GetImplementationID() = 0;2 f) v4 V3 I* C6 _1 Q0 i D
. v$ K$ c3 n3 ?* Q. m4 F% [5 p
void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping" w( J! p* _3 r
2 J& H, R2 X' l2 f+ ?6 G$ K+ N4 O7 A' J& _, Z
void SetMessageOnResult(HWND hWindow, UINT nMessageID);
2 d8 ?; ]( S+ a$ v# a# d TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }% `% t, T$ Y; x9 G7 d
uint16 GetUsedTCPPort() { return m_nTCPPort; }
0 m) Q( Y# w# y d; O uint16 GetUsedUDPPort() { return m_nUDPPort; }
& I$ f; @8 L1 J6 l* Y' s; W, j
& i& A7 p* p! |. U O l; ~7 y k) \- S
// Implementation( b) D% O# Y1 J* d$ V, O3 {- B* i
protected:- N) e# l9 C* o- L) Q" a
volatile TRISTATE m_bUPnPPortsForwarded;- ?* s0 t! L ?$ a
void SendResultMessage();
$ @1 I0 _0 d5 | uint16 m_nUDPPort;
! M- o$ v- T( O/ p3 a9 d* D0 p- Y uint16 m_nTCPPort;* J9 T0 a( [6 q3 r+ K6 p
uint16 m_nTCPWebPort;
& p6 w( e% h* ~: d; m bool m_bCheckAndRefresh;9 s5 \6 T. E* N: s& J; m9 S+ V
1 a, D2 u6 ]3 @( i4 h7 m$ T$ q7 `& L( [5 R$ U ^/ s3 w
private:
- c* O2 D: e2 [ HWND m_hResultMessageWindow;
& j7 {; _/ d' u1 ? UINT m_nResultMessageID;
/ c R# g" x0 h) w
. c; {, j2 S& @& W+ _4 W6 i) Q: t. D9 G4 n4 }6 _4 c- |
};# J# t0 s: i, }- ^2 n
7 l5 s; I0 K1 C4 T ~0 P
8 ]/ J( a0 [( _5 a- N// Dummy Implementation to be used when no other implementation is available9 m c! s, _+ S* G, [
class CUPnPImplNone: public CUPnPImpl# j; m3 J; p1 U% t: z( y1 M
{) j: o! a% d5 |
public:
% p0 f4 F. f9 [ virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }
! v0 R! \: D$ y# y8 o/ h! q P: K virtual bool CheckAndRefresh() { return false; }: Q6 w8 Q9 V( }) U8 t2 B9 D
virtual void StopAsyncFind() { }) u$ b, ?8 x7 K9 ?/ X( H
virtual void DeletePorts() { }: G7 b; ?- ]/ P1 V
virtual bool IsReady() { return false; }
8 a3 S, h( S8 q: L! E virtual int GetImplementationID() { return UPNP_IMPL_NONE; }
# ]1 _2 [6 Y/ ~0 ]" m! M0 T8 d" W};
9 r/ o0 d+ x. r8 }7 H) |5 Q: P9 i
l6 P+ s9 w. \
M: A3 s/ N* Z' E0 A. W/////////////////////////////////////
5 L3 ~. T' ]$ ?/ R) Y$ @//下面是使用windows操作系统自带的UPNP功能的子类
Z6 P9 w, t& U( `. g
+ u+ H8 q% V3 g: w; e' u8 s
9 |2 z+ Q% S7 ~* u$ I#pragma once
; J7 I0 f& `, ~5 U- ~#pragma warning( disable: 4355 )/ g" w* F4 E, ^% G( P3 ^
; T, }, K B: S4 Z; `( s9 c2 c! ]' w; y8 A
#include "UPnPImpl.h"
$ @" p/ K4 J) ]) e, d#include <upnp.h>
1 t- L. P) r8 z! L% Y#include <iphlpapi.h>
( P# Z m+ N. l$ w#include <comdef.h>+ U) i7 \7 ~% o; |% }: S& M) b
#include <winsvc.h>$ C: @1 S9 x/ U% s: t- B
( z! v5 p. y% I- q* X9 o, [8 i
+ G- m- n0 _* Q8 p#include <vector>8 s+ m! ^. N; I
#include <exception> m% r4 E4 p2 Q6 Z9 I! H5 d
#include <functional>
$ F) e- h( E, H4 t& {0 }4 k; {+ @: u' }* `* R% J# H
/ y; L$ ]* v* ^0 i! `) a* n6 Y8 u X l4 C a
6 G( v( N; F1 C& C& Q4 e. jtypedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;
- I( p! A' E# T6 e$ Ltypedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;
; R, S; W; v- L/ Atypedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;
4 O! g, i" n3 H# S6 H. Ltypedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;4 I" K0 o, P4 F; A8 O
typedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;+ z) @ V! l. K" g8 ^- q' N' R
typedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;! _' [) \ p& z
typedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;5 x$ Q# M- f. {$ q' T
$ Y9 L% i E; j' {4 B/ i- U7 P% r7 _$ k4 d, h8 K/ O: N; W
typedef DWORD (WINAPI* TGetBestInterface) (3 g. X+ F1 T$ R2 _$ J! V- @7 Y& x
IPAddr dwDestAddr,
$ }, `/ b% \1 Q: }& E6 v& A PDWORD pdwBestIfIndex( j6 D; M, W$ r7 w% J
);
: p1 c# X4 B" O9 ^4 L. ^1 |6 b& Y! r+ V' Q4 d2 }, A R
; P0 u u* q/ D8 E# T/ A) ztypedef DWORD (WINAPI* TGetIpAddrTable) (
, i5 Y% b# @7 _# O PMIB_IPADDRTABLE pIpAddrTable,
; F" {% m8 F; ]- v% s PULONG pdwSize,6 d+ u: [/ `! ~2 ]* d
BOOL bOrder7 F* |5 [' t6 o: ]4 i- c. W
);( R$ y: b7 f! t0 j$ |. x
$ V6 ^# f r% z
% r( g, v: }* R$ p
typedef DWORD (WINAPI* TGetIfEntry) (
5 i8 o% k' \6 I. l' g2 V PMIB_IFROW pIfRow3 e" _7 i. I" a$ D" S
);
# j) b" S' ?3 v; D! W3 g# D. z! ?* y0 Y, s
& J, A; w8 X7 H( U; d
CString translateUPnPResult(HRESULT hr);! j& k4 h- @3 y- R
HRESULT UPnPMessage(HRESULT hr);
4 a2 a5 o4 H& X& ~( ?% \' j p* ^% M+ ~& b
* D2 c/ S' P) z* ^/ X' e
class CUPnPImplWinServ: public CUPnPImpl1 O' c5 n! z7 N& ]5 ]- P) a/ {6 h
{
8 z; s: b. x1 b8 q( Q friend class CDeviceFinderCallback;
) |- H# I$ f1 p# ` friend class CServiceCallback;" ^* G8 `# a3 `% M) T% R
// Construction
: d. s0 u4 H, B' u8 @3 r! Ypublic:
" @4 S8 c& c4 a! T virtual ~CUPnPImplWinServ();
( Z; H9 y: X X' ] CUPnPImplWinServ();
% P, O, u( Q$ V6 Z/ s' g$ N2 ]! C+ d. x' M4 b' e3 F* V
( t1 m t0 @( k8 E
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }
5 W. U# z( D; @; D7 e9 Q virtual void StopAsyncFind();! R/ z" X/ Z+ t: U9 I
virtual void DeletePorts();+ B% n1 m7 H0 @8 |; F: _
virtual bool IsReady();
- o" J0 ~9 N7 H% G: n1 T) n virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }# r- T1 r/ B+ T% P- h
; R2 q/ ^4 f: C- Q! P; o
- [' \! ~0 Q. Q7 T l // No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)) Z4 Z7 u. V1 v* E9 I8 f& M
// the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later. X$ y7 V* S; u6 T% T7 s
virtual bool CheckAndRefresh() { return false; };8 C, O" T3 g8 r, _) j
4 o/ d: z, r. ?8 ~
* f( u, i( J9 p9 {# U. Iprotected:
& g( o0 r& h9 j( o- Q void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);6 A/ X. V+ B/ f" q, r
void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);* u2 U" E* k5 C7 O9 P
void RemoveDevice(CComBSTR bsUDN);0 I0 T. |* f( f ` H# ^
bool OnSearchComplete();
5 a" |5 P# d1 `, m$ K void Init();; M$ ?0 M/ _& Y- }
1 H: z: _( a. G1 I o+ U: O& V
, u6 `7 k( S- L0 e: y0 M- g
inline bool IsAsyncFindRunning() 4 \( T- l6 N# }0 v, m6 O$ o
{. i9 i }1 M# S# i+ i: h
if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )
* b6 j% Z4 {6 [9 `) T {4 d" O7 L) P- ], A& f; p, z! l+ c' N
m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );. ?" R7 N F7 { ?' g
m_bAsyncFindRunning = false;
& K9 ?5 ?7 t8 I' p$ F }
7 Q0 p. [* W4 M7 e5 t8 L; g0 f7 [ MSG msg;
/ S& K) g( w5 E7 ^! R while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )) _+ h& a/ w3 u2 r2 t0 X3 M3 N
{
# ?; x6 h U) [, T" A0 g8 e TranslateMessage( &msg );$ ]* g/ U1 [+ r( u! V
DispatchMessage( &msg );
& R" P, h+ a; z }' `0 ]- F1 H; ^) A. d5 P9 _
return m_bAsyncFindRunning;8 e- a) m. v: K1 v" A$ F
}! J8 r* I% S" s* v) h0 x
5 j$ f6 x8 u% T
4 X& ?1 W8 p/ X0 r TRISTATE m_bUPnPDeviceConnected;0 Q2 u4 d z7 Z, V$ s6 y! }: m7 v
0 R# B- S4 j5 f0 I
4 h2 c- @" n8 C* u// Implementation3 O9 e$ S- M7 R1 h) w; t
// API functions0 m: T$ N" w; T; y" \
SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);+ [' c! y9 v8 K8 l; C* K
SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);
" h" E% k6 L) k% Y2 I BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);
0 v7 s2 b; h' E5 {/ Y BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);. ^1 T7 y' s8 b
BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);
. d" M; M: c5 U3 F$ e. G: Y BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);
& d/ k5 W3 S! r3 [. S9 s0 F0 A4 W( }" F# r/ L) }' e. j% g$ h
1 G/ ^1 G' V9 v& ~ TGetBestInterface m_pfGetBestInterface;
4 I3 G, F3 G) l2 u& w, C, p TGetIpAddrTable m_pfGetIpAddrTable;# I2 c# _8 E6 q- H% i& ~9 C; {
TGetIfEntry m_pfGetIfEntry;
0 j8 u& p8 U) x! @: H* X& W' _
' y# {/ I+ p5 f+ I# s
5 D$ r; @7 n, t7 V" G static FinderPointer CreateFinderInstance();
# }- v$ \: P) t( d* K5 ~- ^' O struct FindDevice : std::unary_function< DevicePointer, bool >2 u& }& }: k }* M/ ~) m
{
: \5 X; T4 v1 p; y# K4 l" W FindDevice(const CComBSTR& udn) : m_udn( udn ) {}# ]: w$ w; {# i
result_type operator()(argument_type device) const
2 H! [2 f3 X6 i {6 x$ E d; Y' W$ i! S
CComBSTR deviceName;9 ]9 @3 E! M0 L, g7 X
HRESULT hr = device->get_UniqueDeviceName( &deviceName );# C" A ^0 S O1 C5 {
! l) O; y- T$ ^0 Q
* o) S- C% T6 k- N( @% A if ( FAILED( hr ) )
3 b& i. ^& A) S8 T! Y1 n return UPnPMessage( hr ), false;) w5 B, }+ R( `
0 R* I6 }; h6 s# u( x3 J0 f; j* `. q! l; c
return wcscmp( deviceName.m_str, m_udn ) == 0;6 c1 w$ o; o( W" x, Y- f
}% n$ n1 v, N$ M' |5 I" J8 m& W
CComBSTR m_udn;
J9 t+ O+ ~" c: V5 J% | };! I& s3 u1 q3 q4 M% I9 p7 Z
8 S- S: Z- ^9 ?' O! s3 L4 ?" C7 A+ d
void ProcessAsyncFind(CComBSTR bsSearchType);
- b6 h# J: R! {9 i$ K6 _. Q HRESULT GetDeviceServices(DevicePointer pDevice);/ \* I" q8 j; [9 c" s" V' u5 Q2 `
void StartPortMapping();4 ^2 g/ m. S& J4 x* [4 T; x
HRESULT MapPort(const ServicePointer& service);
" t1 D. {$ _% t, |+ n; X+ ` void DeleteExistingPortMappings(ServicePointer pService);' H4 i7 M* \% s; q
void CreatePortMappings(ServicePointer pService);
5 F3 T' D' h f% m# N8 ~. k: N% U% Z8 x HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);
" {; b, o) v; ?1 A- Y. j7 Y HRESULT InvokeAction(ServicePointer pService, CComBSTR action,
- c6 q' m+ f5 \( d+ { LPCTSTR pszInArgString, CString& strResult);
; L) f; S# Z3 i Q# a, k( ~# r( b void StopUPnPService();
7 W2 D+ F G1 l7 P3 R# k1 p9 I( u: T+ B6 y% ~
9 w3 Q. C2 T6 x& { // Utility functions
* G0 T0 F6 c M; @0 F1 A/ {$ ~; J. O8 f HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);
7 f* x: _2 G9 z) k& f1 ^! U! w INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);: Y( [0 u' {" U; r6 [" M& @4 A) I1 z. D$ D
INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);
. e' X1 p) J f8 I void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);
% U, e; G7 K+ ^. X HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);
8 Q, W# \% _/ a8 A HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);
- | P# g/ t7 q$ x z CString GetLocalRoutableIP(ServicePointer pService);, ^" F! T' ]) P; R* w& {3 X
$ e! y2 \2 X5 a M7 H
- Q- _) J) F) _6 @6 h
// Private members( e7 [5 q; a' R
private:
2 ~7 V* V" O) E/ R8 c2 O DWORD m_tLastEvent; // When the last event was received?
( D0 T3 N) K& Z- Q( F. G std::vector< DevicePointer > m_pDevices;: e) ?+ o k7 } D, H8 U
std::vector< ServicePointer > m_pServices;
! b1 a7 S0 w2 J; S FinderPointer m_pDeviceFinder;
9 j( L7 q; {) h& `- g DeviceFinderCallback m_pDeviceFinderCallback;
3 ^+ H. c; ]% v5 q8 }, } ServiceCallback m_pServiceCallback;
2 ]. L: K% Q) M4 P% s8 n+ @4 O' U; z
; R. x( G7 D& c5 T$ K LONG m_nAsyncFindHandle;
! m( L" p' {# p7 q8 Z% z2 F bool m_bCOM;/ w- p" }: @ ?; l& P# c
bool m_bPortIsFree;
8 g9 D/ H) [/ k8 i5 K/ n* Q CString m_sLocalIP;
5 k, P3 T3 l B2 D% G4 F CString m_sExternalIP;
; Z4 l' H- [9 ?) s bool m_bADSL; // Is the device ADSL?
1 z! E5 Q3 R6 R- \; z! n bool m_ADSLFailed; // Did port mapping failed for the ADSL device?
! r: p3 b3 @% U- @ bool m_bInited;
, n4 X+ l& y3 G' U& \0 ]9 o bool m_bAsyncFindRunning;
( h2 }7 L' n9 {* \& n% l HMODULE m_hADVAPI32_DLL;; K5 i! l( a: M9 e
HMODULE m_hIPHLPAPI_DLL;
, f+ N; J7 f8 m5 p7 b1 e bool m_bSecondTry;: X- C' B% I* T' c& T" W) l
bool m_bServiceStartedByEmule;
7 K4 v) A/ M$ @5 u6 D bool m_bDisableWANIPSetup;
9 z: G E# ]5 B8 f% c3 m bool m_bDisableWANPPPSetup;
3 u8 h1 }' |9 s, C6 Y- y: {
* ^3 O" a! Q) M5 b& ]( a5 V7 E( T$ W% f+ I" P! @/ K6 ]' V! L
};
; R( M$ e2 A, }$ L# H/ M4 j7 \* O! i9 H( f9 t8 x* }5 p6 l
# m3 s" W0 l, N+ ]
// DeviceFinder Callback
9 `& U+ t R1 K, q' Lclass CDeviceFinderCallback' Z }0 z9 S: l0 e
: public IUPnPDeviceFinderCallback; y- p, E G3 n# f: I
{
& i& z6 i- E/ Gpublic:9 R( f. v& {) q
CDeviceFinderCallback(CUPnPImplWinServ& instance)8 Z0 }/ P# i3 V! L! B, V# C
: m_instance( instance )1 g8 V. E( N: N/ }
{ m_lRefCount = 0; }
. X# ~) F+ m7 H; \ d7 R& E
! D' O3 O6 ]' y2 c, @6 @5 P4 ?/ A$ E" [* F! B7 k
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
# t+ I9 L4 z; p* d9 X6 j, H& i STDMETHODIMP_(ULONG) AddRef(); q }, E5 q4 Y/ T
STDMETHODIMP_(ULONG) Release();6 N* l9 E2 _4 T7 {$ R
7 ]4 R$ T9 N, {
0 @9 f& t9 T- @1 h! Z// implementation5 t6 L8 j. U( s3 q2 V% g8 w. d
private: Y5 [+ l- w4 r+ y# g+ C" y
HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice); L9 X( w/ C2 t
HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);8 h) y8 d. U4 Z: M. \" Q
HRESULT __stdcall SearchComplete(LONG nFindData);9 R2 O5 J0 k u0 \% L8 u8 y8 `' G6 K$ P
) O# U" H+ j5 Q! {
# W1 q: u( A- @private:# Q' ~' F9 j/ T! b; w3 M) C4 Z" t' m
CUPnPImplWinServ& m_instance;" Z. U' [/ w& R, y3 @2 z0 ^0 s
LONG m_lRefCount;
+ ^2 _% S. ~ x};
( M( o; I0 F8 }* i/ _( D h$ W X+ C7 g; Q
/ x* s( q1 ~2 p2 Q2 ~2 m! e! _0 ?6 W
// Service Callback + H+ U- ?4 ~& ~/ P) R5 N3 u9 R) i2 d5 g
class CServiceCallback
$ @5 ] C: t( Q8 k; V9 |1 y8 y : public IUPnPServiceCallback
+ r9 z3 g- M8 x2 G{
. m7 I3 p5 s' x: i' Wpublic:
+ r# ]) X T0 n: X# i( [ CServiceCallback(CUPnPImplWinServ& instance)+ a* d# ?. |! ?. g
: m_instance( instance )9 x4 y/ R7 ^* y5 M& I; B* f
{ m_lRefCount = 0; }
+ a7 n E; i" t
4 t6 ~. ^8 ?5 D STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
5 s% ^1 S! F5 Z0 [; P/ X( g STDMETHODIMP_(ULONG) AddRef();1 m9 y' J( X% f' Z! e
STDMETHODIMP_(ULONG) Release();
* V' b* d& Q! m+ p. P+ A2 q% E" g0 Y# o, \6 |; J2 [
- V/ y% U5 C+ b' `4 \6 W' D- _
// implementation3 o0 p% I5 b4 [8 c' v& M
private:( }7 z6 `( N$ E9 [' N0 [, Y- C" Z
HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);
$ z: R! S, L. R HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);+ K [' g' q0 K: ]* J; ^8 c
' y$ W" F- {# S+ N5 w T+ T9 [5 h
2 C' d8 L& n* x. C9 Vprivate:8 P5 t* c- [! {7 H2 Q% ]( i2 P
CUPnPImplWinServ& m_instance;" V& @* ` q# R0 v2 K1 n
LONG m_lRefCount;% U; j2 ?- D3 _" o) ~+ L9 K5 h
};
( N, l% Y7 m/ t) J2 \5 }# h" i: Q3 Z$ [& w% ~' H
2 g, r3 z3 Z+ p8 |4 i9 c& M
/////////////////////////////////////////////////4 _3 y: q* T' Q/ x
1 j, ^+ [6 ]) y' Y G$ m2 V, y% v
使用时只需要使用抽象类的接口。5 {+ h' P' c: Q b3 m* P
CUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.
: u6 Q2 ?7 w1 K! j0 k( g) mCUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.
0 b4 f! ]5 {; ]8 ?0 Y/ a+ fCUPnPImpl::StopAsyncFind停止设备查找.
5 C& {) I1 B9 e/ \/ \3 eCUPnPImpl::DeletePorts删除端口映射. |
|