|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule,
" p5 {3 N7 {- D/ |
; S9 ]/ l9 _6 a' ^. {2 h/ d. k0 `4 \' u# Y: o( k
///////////////////////////////////////////; h( Q6 M# z* z) t" U; z, m
//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.
4 @+ Y! w! q$ p0 s0 g4 V0 C3 R/ N
/ F$ Z. F* w* ?7 y, b
% v$ P5 ]( r) k) v" D" r1 A! u#pragma once' C: j+ I0 P2 [0 @, h+ e
#include <exception>
+ {) s) E% |* A1 f
9 ^& R e6 d6 D1 s( T2 z& D, M8 f# Z7 @
enum TRISTATE{
. m' D6 P% l% i! K# f+ c# y( E TRIS_FALSE,9 M! G X- Q @
TRIS_UNKNOWN,
2 n9 }9 c0 B5 ^& }7 Q/ ` TRIS_TRUE6 K( R. [2 [% A N9 x4 y7 [
};9 e# b: c; `( w& c/ [/ @
; w9 u- F- @4 A: s
; S f% }4 x$ A9 e% I% E5 Y% g5 C& ienum UPNP_IMPLEMENTATION{( I! f! r v! }! ?
UPNP_IMPL_WINDOWSERVICE = 0,2 N) r- @. T# ^6 ?
UPNP_IMPL_MINIUPNPLIB,
, z* r/ l8 Q3 v! S UPNP_IMPL_NONE /*last*/
( u- \3 a7 h. t4 i2 x" H3 D2 _};! f6 u& q; x% C8 ^0 m& J
& P+ v; ]7 B R5 S2 v+ h7 O* S$ e& D- l. q# t. ^
, N1 P6 k3 z8 U( U# t( ^; D# b( r$ Q0 l7 o) @/ g% {6 ?; p. U2 |
class CUPnPImpl6 b- W9 o# D. E* S: ]
{2 G9 H3 M; _. y
public:
% G1 G# {8 Q+ h1 u CUPnPImpl();9 f( w* X4 w8 O* i3 j
virtual ~CUPnPImpl();
/ I% R. `' W6 T struct UPnPError : std::exception {};
% z7 w& |7 A s2 z# n, F enum {
, y# ]8 q2 ~' U( S* i UPNP_OK,
/ m+ b* m' D" y' f K& `9 b; M6 e% o UPNP_FAILED,
+ U( V& G# T' ~4 e! U UPNP_TIMEOUT
2 y) F( M1 i7 M. n4 T };8 f" N& V% d/ A4 U/ b: }3 I
" ^! F0 Y0 ?6 B8 a6 S Y- m. U/ o
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0; D5 [( b F3 k: P$ d
virtual bool CheckAndRefresh() = 0;
4 z* d% h, ^6 G. M* w virtual void StopAsyncFind() = 0;( c5 f9 s6 W* m8 s) h- p p! u0 ^2 a; j
virtual void DeletePorts() = 0;
4 A$ v2 {4 H0 k1 {' M virtual bool IsReady() = 0;
! K+ ~5 f) L: c* o, X- ^" \/ r virtual int GetImplementationID() = 0;
# `, @& S" H& H N6 Y8 a7 _ 9 a5 i# P7 _9 Q2 m+ \ W5 E
void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping
8 _; w$ g6 p0 o; `' i( ?% E0 K8 `' @$ r- y. S
. j8 ?. j; P- W: U d: l2 p void SetMessageOnResult(HWND hWindow, UINT nMessageID);
4 P* a- c5 N+ _' g3 V TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }
8 v* K/ J. ?2 {1 X! @# _, ]/ R uint16 GetUsedTCPPort() { return m_nTCPPort; }1 [+ I0 X* v3 W3 e/ ^
uint16 GetUsedUDPPort() { return m_nUDPPort; }
# y# \' V2 P3 _* Z. b
1 }2 g5 @. ^ ]7 H9 p
! U8 s1 a1 }7 f! e( b! P$ H// Implementation
5 `" _' U' _- Bprotected:/ f* ~ w& X5 S
volatile TRISTATE m_bUPnPPortsForwarded;/ A N e, O) o. }2 g$ P' V7 i
void SendResultMessage();2 v& z8 [4 M* L! W; A; J' A; ?
uint16 m_nUDPPort;
3 S& M# E" q1 O3 l$ B& j( U/ ^ uint16 m_nTCPPort;
/ F4 }" H/ E8 C5 N% T uint16 m_nTCPWebPort;! C9 W! W1 q7 Y) E
bool m_bCheckAndRefresh;
' a2 r9 p. T! a2 O, Y" Q! b {$ Q/ `! H, ~7 ~4 q% t
3 O" @% m8 g% c- i* Z
private:
7 G `9 ^2 D& T" s: W3 l5 g HWND m_hResultMessageWindow;7 r, c0 G* c7 K3 f% l7 p
UINT m_nResultMessageID;
% p4 ]" }, t. H, d; f0 S' O& y9 W# i2 ]7 l/ h" R# |, Q( y1 t
+ g. M0 [2 w9 h' s# f, {: P
};
6 c/ r3 I: y6 b5 U7 {; b+ }/ K
( ~1 x- H8 W) o$ g, ^# z
+ Y& s8 u( ?: ^' s) p( Y5 O4 ]// Dummy Implementation to be used when no other implementation is available/ a5 C% ?2 _3 q$ F0 W
class CUPnPImplNone: public CUPnPImpl
# f2 l& o; Z4 {7 s9 S# b; O{
/ l* y! }+ t6 t7 [+ Q3 y+ |5 Qpublic:
) p& u7 _, L7 U virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }
0 a6 c, h+ U; j! L; @5 } virtual bool CheckAndRefresh() { return false; }: o) } W+ V. P3 @
virtual void StopAsyncFind() { }
3 T" A* m& ]% s1 D: J* g( N" V virtual void DeletePorts() { }! N8 E* B) u- ^& H9 B2 T+ \- {
virtual bool IsReady() { return false; }- R$ E+ l4 E: s6 y; S& Y
virtual int GetImplementationID() { return UPNP_IMPL_NONE; }: O- B# L' \0 @3 U+ l
};
! Z0 g* } e' g) c+ F
9 t% O2 b) @8 V! Z6 O) a6 R
$ ]3 p: z# t# P5 F3 k/////////////////////////////////////
( F' |# E# V8 {0 G* h//下面是使用windows操作系统自带的UPNP功能的子类
3 N j* T6 m2 ?2 t, b/ H5 \/ ?
: F% o) L# ] R1 q! h$ k( Z- Z7 F. W0 V% l2 q+ v$ Y$ e) r
#pragma once+ X& [, C; C! q7 v* }+ x
#pragma warning( disable: 4355 )
1 ?$ B% b) h b# ~9 [* q, a. k% @0 F
3 S1 I/ n4 ^) h: S# f7 J1 d* u' g#include "UPnPImpl.h" X/ Y/ V, I( N5 b) f
#include <upnp.h>6 N# z" O* k- D1 G/ {* ~) u5 c
#include <iphlpapi.h>
: Z4 }: B# R1 ~: p7 f#include <comdef.h>
7 {5 \2 y r/ v' y#include <winsvc.h>$ ~ Q U' y* h! ` v& W; Z- B
. r4 q, Q n1 Z+ Q6 ~$ H
4 H- [( p# V8 F3 T* z! a" F
#include <vector>: G, e: k3 @- X) Q
#include <exception># K( m o' W$ w B9 m
#include <functional>5 Y2 } S6 F1 L- b. h& L
! x8 H* T1 B8 w, T# P/ k$ p8 j1 V* O* t4 V. `. C9 \1 D4 q% h0 q4 f
2 t2 q$ Y: r3 @6 Q
# H' j, m( e8 }
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;, i0 E5 M% s0 d" V0 X* V
typedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;/ o" d# v( }+ n) m
typedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;. F! Q; h. v$ f: L" V# X
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;
6 U9 j2 z0 W0 }' p! I+ O! g: otypedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;
& D/ a- h# d% |6 @; |' {% G# I& btypedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;
: y/ h4 q+ W* I* k2 K x; Ztypedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;/ C% ]4 J( G$ M- [' u
& {4 R1 o) W6 L. L$ G! M$ l
% z! e1 C, P o
typedef DWORD (WINAPI* TGetBestInterface) (
* y6 {& D9 J- S* O* V, i IPAddr dwDestAddr,4 C, x' Y U' {' G
PDWORD pdwBestIfIndex
% g. `+ |: A" J);' @0 @5 x8 c( ?8 K
' ~, Y* H+ I5 Z- B8 _# ?* R b
! ^( q# j* y3 W2 b. Mtypedef DWORD (WINAPI* TGetIpAddrTable) (& F6 A! u5 j i' [+ Q3 C8 S
PMIB_IPADDRTABLE pIpAddrTable,
}! W, u* S W% p$ d c! ^4 Y z( T PULONG pdwSize,
( |% w6 E4 W4 k; i BOOL bOrder
! [6 K2 Q8 |0 ~8 A3 d; i, K) j$ p6 x);( ?4 k9 z! j( ?
8 d: r9 o; N! P! C
8 f: L n O) }typedef DWORD (WINAPI* TGetIfEntry) (! S! b# @% }% Y5 K6 S* h! `1 m
PMIB_IFROW pIfRow
3 ~" X% a8 H4 w/ i, \);$ F$ L) M$ ?: h4 Y8 M
3 \8 V. I5 H" q4 o! G) i6 a0 f- b7 ^+ U) w# C* J) P
CString translateUPnPResult(HRESULT hr);
# m6 V5 c ~) ]' |% Z3 ]6 }HRESULT UPnPMessage(HRESULT hr);
8 `% R: N& `% N6 E
% X* f- v4 o$ N4 o [2 r0 }6 I) x
class CUPnPImplWinServ: public CUPnPImpl
3 c. l) W! j. u! ^4 t4 W; z{
, X, k3 M* e- ~$ R9 e friend class CDeviceFinderCallback;
! v# _" \/ }! _# Y; ?, [6 n2 @+ J friend class CServiceCallback;- d4 L, w- n9 U x% G
// Construction5 }' g# [) g+ y. L
public:
- @/ A+ X0 h% } S+ [ virtual ~CUPnPImplWinServ();
1 k: e* o9 h5 F7 n CUPnPImplWinServ();
+ }- v0 N9 d# N' J
; v$ w/ v5 K' r: ]
- k& J' H. {2 p( ~ virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }
5 t' _. B6 x" u7 R3 F R, ? virtual void StopAsyncFind();8 G$ t s& D; c
virtual void DeletePorts();5 h: }( d9 P0 U9 }! k
virtual bool IsReady();4 U) w% a1 d4 F: _, ]6 W
virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }; u9 ?$ E3 J3 F; O/ q0 `
" M! L' ? v! e- i5 y" ?, c0 L4 v: o- P7 k- H0 s
// No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)
1 I- I& U4 m# ^$ r- s t' H+ ^ // the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later
$ d8 m% `; f3 U virtual bool CheckAndRefresh() { return false; };* E5 p5 W, N( ~& T+ t# y2 c. ~
3 u! P( _" n' e
0 y( M3 X: V1 F
protected:
: F5 K% X% R- P, J void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);
5 _! A) R& X4 `& { @4 } void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);
/ F: t, M, [- T) \# G void RemoveDevice(CComBSTR bsUDN);" b9 }: L9 ^3 o6 o
bool OnSearchComplete();
8 Z8 q/ C( K; K" e, Q& k# h; h+ a+ l void Init();# ]/ Y8 o3 U, {( y( `1 E8 a% N* T
& A; Q, z" f; g6 M: g6 i
' x0 E# a( `1 _+ D inline bool IsAsyncFindRunning()
% G" U8 Q" z {! c2 C) N {
5 `6 n5 i: w" m0 S7 X! B if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )% h; `) M1 d. w
{9 Y, V4 Z4 g/ \' q/ g
m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );3 P. x2 X# z& g$ Q' y
m_bAsyncFindRunning = false;9 N* w# r& J) e4 O M
}. d, R- G( q9 ~; k5 z$ K" i
MSG msg;
. i/ w- l) j1 \9 }- Q4 O- ` while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
4 {. y0 U) e3 b) U3 X; ? {) F ~( R/ s* [6 j1 s1 C$ x! `( E
TranslateMessage( &msg );
+ n+ G2 u8 |2 ^; S* i7 }7 N3 w: g3 S9 I DispatchMessage( &msg );0 L; t( y# O; \1 U9 J. }. c! y
}
4 [; g! o) m# {0 L return m_bAsyncFindRunning;! r# I v0 u5 P1 T6 G J" H) c
}
) t" h0 e3 A/ v5 c
% W7 [. O5 H) E6 {5 ]. k5 L+ ^8 n) F8 A: @+ F
TRISTATE m_bUPnPDeviceConnected;6 a3 B {! N5 `, H" k3 o
7 {9 m. k9 i; b. Z: H
7 _3 g. L+ n' V! d
// Implementation
/ t7 P3 |# ^2 Y. z // API functions
0 i2 ?/ m% B' F& T% n( s" J SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);
# C: @8 x' Y& j' ]% e) k4 p) F, ? SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);
2 s! s9 r5 y; k7 m+ _) S BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);
" P. |- O* e4 n5 Q r& d0 G+ D BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);
4 H& k# z, X# l+ u6 C BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);/ e$ u" l1 s8 U( _1 U
BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);
! M. }& O! x& X3 O! D# o- ^* h6 g0 m/ ~ _$ {: z. I" F
' m% ~+ F3 R1 m l+ d% z5 w8 }; g TGetBestInterface m_pfGetBestInterface;' Y5 O2 n l7 {' Q7 H
TGetIpAddrTable m_pfGetIpAddrTable;/ o! g7 |% L; }7 ~
TGetIfEntry m_pfGetIfEntry;
7 K% Z |# O4 K0 \
" s+ |5 d: x, E" {8 k4 M
' _( |- A1 B8 @' J& r* a static FinderPointer CreateFinderInstance();, N" P6 B7 ^" o7 L( b; y" U8 a/ t, h
struct FindDevice : std::unary_function< DevicePointer, bool >- ]+ [ O, W% X& H6 R
{
8 U! f* |4 m+ t FindDevice(const CComBSTR& udn) : m_udn( udn ) {}. @& ]; l' Q3 c/ c. S
result_type operator()(argument_type device) const
2 s+ [' U8 ?; s {
0 @* a+ P) W1 a- { {& g7 p CComBSTR deviceName;
. E6 J& K0 i- f# k( r& ? HRESULT hr = device->get_UniqueDeviceName( &deviceName );
; e( D" s* Q K" C) b! I$ _$ |" j. \" Z+ h+ z
& q3 B' J7 B. Q& O! ?% s if ( FAILED( hr ) )
4 T$ Q8 l# L+ S) X: ^8 D4 K# G return UPnPMessage( hr ), false;$ }7 u0 C/ D9 `0 {: X
Y+ M! e$ g; M9 m+ A/ ]! ^
1 w- q/ H, ~4 z; V return wcscmp( deviceName.m_str, m_udn ) == 0;- Y! `9 ]6 q' A& y8 m$ @3 i
}6 e. ?6 F% S' y7 q8 Q4 _
CComBSTR m_udn;4 A- s" c0 D. w8 C! r7 o: k/ O( e
};
, v- d' d: s7 G/ ]- C% O
- V0 T) W9 [& B3 C' ^1 S) w void ProcessAsyncFind(CComBSTR bsSearchType);
' n* d7 H, ^+ G HRESULT GetDeviceServices(DevicePointer pDevice);
3 Y/ O% \8 Z& a2 Q void StartPortMapping();. U# v, x, ^, I* g* {
HRESULT MapPort(const ServicePointer& service);/ F: d+ ?9 }. C, ~% w. y- p; \
void DeleteExistingPortMappings(ServicePointer pService);
( g4 f& A3 D7 ]1 S3 C; g void CreatePortMappings(ServicePointer pService);
& v" H$ L' x4 E HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);
9 q" E6 q4 d8 |+ _; H HRESULT InvokeAction(ServicePointer pService, CComBSTR action,
! K; U/ `/ h7 a9 w) K/ B LPCTSTR pszInArgString, CString& strResult);
9 {3 I( \" g- v3 @- _ void StopUPnPService();
- q( a2 ~& g' }2 Q6 m# @) W
' j, x6 m1 n4 O! S( K/ \: d
) w6 F( @# |1 l; H // Utility functions
/ @" ~& m6 h8 u* t9 C2 C HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);
$ L" L, C. F5 ^+ S INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);, w" D( l# b, M5 R
INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);$ S2 R; v1 I/ F' }/ d% f4 l& k6 s
void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);$ [$ B7 W! m* N6 e8 d, y' P$ m
HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound); m% t W; T! T, F
HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);8 k1 R u8 M9 y) r) E. y5 G5 {1 {
CString GetLocalRoutableIP(ServicePointer pService);8 j! V3 y6 ~6 o4 ?% |; w
% o+ F) H# ]4 y+ E t2 A/ [
6 j: i" y: n+ R. B& g// Private members
+ G' K6 X4 d! U$ O& p! U$ iprivate:: s4 s: }) c& C [" i; [
DWORD m_tLastEvent; // When the last event was received?
! t: b# p# ^! y# X std::vector< DevicePointer > m_pDevices;
( | P0 D+ `9 o: u+ x std::vector< ServicePointer > m_pServices;
6 Z p' O- R- g5 C2 ^ FinderPointer m_pDeviceFinder;' h. t' c! W! ]- [( Z
DeviceFinderCallback m_pDeviceFinderCallback;- \, }1 R5 J8 o) m. |
ServiceCallback m_pServiceCallback;9 Z. T* B$ k' q4 P& a
; c3 a+ y; }1 z T4 m, Q
E: p0 a! Z7 B5 k3 t# p LONG m_nAsyncFindHandle;
) v9 b3 P: G. p6 D' `( X" d bool m_bCOM;
4 l, [$ y! k2 e: J% N0 V bool m_bPortIsFree;( B- a5 X6 ]: q7 C+ |
CString m_sLocalIP;
9 y5 \2 W8 `: r" I- M% R: ?0 |8 w3 L CString m_sExternalIP;# R. A& Q. {, }% _
bool m_bADSL; // Is the device ADSL?
* d3 w1 v7 \3 S7 i bool m_ADSLFailed; // Did port mapping failed for the ADSL device?) w5 F6 D; f: R' h. _
bool m_bInited;5 o4 C% \! O% Y- R* U, \
bool m_bAsyncFindRunning;0 z! H- ?3 W3 ^' I+ ^6 G) T7 h2 o
HMODULE m_hADVAPI32_DLL;
8 h) E! e* e' h8 E, y HMODULE m_hIPHLPAPI_DLL;
" f. K* |" D. U) F3 \% x bool m_bSecondTry;! U6 V3 G( L3 r8 P
bool m_bServiceStartedByEmule;1 d$ q1 D9 \% X0 |1 y" P3 p: [5 p
bool m_bDisableWANIPSetup;
( X8 O' ~! d, C6 l. U bool m_bDisableWANPPPSetup;4 a8 n$ d* P; k e9 H
$ |4 B) w: F; x3 a' I7 v3 A: a1 H5 e' ^2 Y
};; u! U: l% U- S% A9 K+ \3 }
6 U- e+ Z( n {7 s' ^# t
, ]# W# U! {% n+ T2 r. I' b// DeviceFinder Callback
+ y! D7 ~$ A) T$ s2 ?class CDeviceFinderCallback& l& b B6 A9 h& u0 M
: public IUPnPDeviceFinderCallback' L3 Z% F) d- U. ?3 [
{* o3 g- X7 t) W" r& x: R; J1 V5 l
public:
* |1 B. B$ t6 E0 N2 I8 B0 M6 X CDeviceFinderCallback(CUPnPImplWinServ& instance)% B1 y( f3 X) [5 I' @
: m_instance( instance )
* H$ ]! S% A* I8 \7 S( w0 C2 k { m_lRefCount = 0; }
1 v! f& W2 P A! P
/ O* M+ N* v" U; E/ q* a4 T+ [. ~2 j( @$ z9 O& [; v9 g
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);8 s2 l/ Y J' x! p
STDMETHODIMP_(ULONG) AddRef();+ ~3 z& m7 ~% `- I; Z- F
STDMETHODIMP_(ULONG) Release();
* @7 l. H$ a4 Q
" g6 U3 u" B# _) S3 [/ M+ W" u6 H/ f. I. a2 n% f% A
// implementation) G! t0 Y+ u4 h( p* ~$ {
private:
9 P2 ]$ b1 B+ U4 |* p; e4 a. Z! Y2 H HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);/ R- ^( z; i( {3 f b
HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);7 u8 s( j; a+ [+ O8 m0 b
HRESULT __stdcall SearchComplete(LONG nFindData);
; A; D$ I0 J, s+ {: G: b6 c& {# N- M3 b J! U
: T2 L' Q1 E, K( c
private:
) z& n" Q2 ?9 J! b" i CUPnPImplWinServ& m_instance;
$ N q0 V4 h2 k LONG m_lRefCount;
, y3 |, |% P) a. q3 \; j+ W4 H2 L};
3 q: h0 Q3 y6 a, k* u6 T& T& x+ ~* d) ^$ `$ X) G' V
) h4 _9 D* N& ?9 K% X. C// Service Callback
; } y. m0 V; Dclass CServiceCallback& ?: ]7 q' U% q! U4 \0 C8 Q' x% z9 a
: public IUPnPServiceCallback+ \! l7 Y8 k* D
{/ f p3 H+ d* U' {
public:
" q7 g+ \1 X: F* m CServiceCallback(CUPnPImplWinServ& instance)- e+ E; e, O& Y7 w
: m_instance( instance ), Z. A% {$ S3 D0 {! z$ L
{ m_lRefCount = 0; }
w6 C& E% b; W: v
9 |) s1 i4 D% d, G% x STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);2 h. X% q0 [6 L! B& Z1 v' A0 R
STDMETHODIMP_(ULONG) AddRef();
9 o; d. f) {/ ]! b$ u2 |; S STDMETHODIMP_(ULONG) Release();
) ]6 i# S7 i2 m
' t9 ?7 v9 M9 E# l+ M8 x% D' U0 d' p3 ]0 X
// implementation& E7 U9 w- T9 M, @) D, j+ w
private:- ~% ~+ t9 d7 n& x9 V' _
HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);
2 l: Y& u9 `" B. ?/ C: Q9 N HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);
/ D, X8 a4 Z& I5 r- H+ [ r* F# E$ \/ g( F
; Y! H& D, x" J6 f( } ?7 {$ v
private:
( @4 o9 c* f# k2 n& | CUPnPImplWinServ& m_instance;
# y" X( f, C: C$ l( F7 \2 f LONG m_lRefCount;
2 F/ ], ?, }2 ?};$ |- ~) t* p, h9 J: S. K; k
$ d5 w8 z U' j7 F2 {1 }
/ j; b/ v% r! e' N/ M# o* t/////////////////////////////////////////////////* Z$ C5 d; C- b0 O$ n
( l# B+ U1 P! Y8 ?
+ D g5 [- l7 P使用时只需要使用抽象类的接口。' }* z( g' x& g1 z
CUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID., K2 `( q5 J5 I7 p. Q$ f
CUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.. d" N4 N X' A$ ?% `! l+ y3 D& ~
CUPnPImpl::StopAsyncFind停止设备查找.
. w9 s7 U/ U4 f/ ^5 u/ i- NCUPnPImpl::DeletePorts删除端口映射. |
|