|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule,/ b. ?* g3 q1 f- H! w5 {2 S
( k0 s/ C& p+ b( T( K
, l$ G0 ^4 k4 M7 v' a% K& T///////////////////////////////////////////
& ], I' I7 E1 D1 {, `//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.
; F0 G, V, p6 i; Y6 ?3 z8 y% [1 t
0 ~6 }& g9 G) N& T" N" _& s. x' E7 W! ]- L
#pragma once
$ A; B0 g g- t6 n, F6 ]" H. r#include <exception>+ K5 {5 J% C% R2 g8 t& r9 h3 l6 [
; N3 H! M s8 q2 O& Q6 n- |/ ^+ t9 p9 u" F# o" P; V1 O: U5 M
enum TRISTATE{5 ^, [* q- }9 _" _. T5 e
TRIS_FALSE,5 [6 D' v7 E" j, [$ u7 X% k- @3 h
TRIS_UNKNOWN,
! W" d, j# m' C) y0 Y TRIS_TRUE, [' K9 a. u3 E# | ]/ e" S
};
& ~/ H0 N& k* ^# b) M
l5 o# U4 f# s% ~* l& |2 l! B- d6 p/ |* b! ]2 h0 E" y
enum UPNP_IMPLEMENTATION{
- t! j# h6 g, _$ s UPNP_IMPL_WINDOWSERVICE = 0,+ M5 Z5 U/ r. w4 r1 I# a& y
UPNP_IMPL_MINIUPNPLIB,
6 i+ j5 p6 V) D+ ]) O7 `: j* J4 a UPNP_IMPL_NONE /*last*/
2 E; {+ `* Q5 k};2 G0 D3 ~0 O" B: h' l; v* i
F0 V, H% \; H8 m3 }
- y5 ^( G. h- B" y# \9 x
1 c- a' X2 P7 g& Q+ O* J
# N8 g! x' p1 aclass CUPnPImpl o% J* ?1 q! |) b% c. @; y( V, U
{
- @: C8 s$ K' @4 R8 y5 {public:
4 ^8 ]" a& X* l" E' c5 H CUPnPImpl(); j a% [% \1 _0 ^) u
virtual ~CUPnPImpl();# h: Q" Z1 b" A, C4 C5 g! K" W, G
struct UPnPError : std::exception {};$ f9 Y) [; j( l( x: l' \
enum {6 E4 Z( Q$ k" p u7 @+ o! I
UPNP_OK,
9 j9 g% @2 k8 W& w; s UPNP_FAILED,
3 W5 i5 ?' ^, P/ d W9 ` UPNP_TIMEOUT
& r" D( W+ t% x j! S' q };$ L2 w3 L# G+ L! @. d
1 {. a" N" N% z8 i# `. D
" l% N) w7 I9 `4 z virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;
) Q$ k/ C, G3 `# ?+ o" i0 `: o$ l virtual bool CheckAndRefresh() = 0;7 }$ B5 V5 n+ {! C5 u5 C" r
virtual void StopAsyncFind() = 0;$ {' q" ?/ {; z j
virtual void DeletePorts() = 0;
# f8 u1 H. `2 g virtual bool IsReady() = 0;! X8 S6 q7 t/ s# i5 B7 ?: x5 O. l
virtual int GetImplementationID() = 0;3 I: Y' P$ X% c0 S! ]" k1 h
* D. A6 K W1 ~" } void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping% W! t# U: p i( h
4 p! s Q' M( @
9 f, P. b; H) ]$ W* n6 Z void SetMessageOnResult(HWND hWindow, UINT nMessageID);
8 Q' D) ?* e: m( p5 z TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }
$ W: \9 @4 s8 r9 a3 T! d: t uint16 GetUsedTCPPort() { return m_nTCPPort; }' P: B/ J: o% ^* v" A9 M
uint16 GetUsedUDPPort() { return m_nUDPPort; } . w& I, e1 z0 |5 g L
1 ?2 [# B/ c, g: G: A5 E7 k2 J9 I9 T
) u9 v( t) q8 {, ?// Implementation% C: s# X9 {3 p
protected:
8 I/ e: Y& m w6 i1 Y* e volatile TRISTATE m_bUPnPPortsForwarded;- ^4 F7 Y1 d& B6 C: G4 \) U
void SendResultMessage();
' e2 m. ?/ B9 z% L$ g0 W uint16 m_nUDPPort;
4 X7 |9 }! ] Z" e uint16 m_nTCPPort;
9 v* D' [7 R% y$ ]+ {) U9 d( D uint16 m_nTCPWebPort;: m) b7 o4 ]3 p! Y2 X* O) S1 y
bool m_bCheckAndRefresh;
9 H; i% l, P7 d1 ~* L1 M0 ~, V
" U% F4 r% `8 D) T1 T2 U
- m* k2 X8 m( G+ X0 I- }3 M& aprivate:
- a- x3 b; v, \4 c( m c HWND m_hResultMessageWindow;, J$ s& P8 A8 j: y
UINT m_nResultMessageID;
% |+ e( R, f7 `5 R2 F' N* t: O8 m1 t% _* C- o
* \1 w/ {+ f9 ?& E- ?) y; q/ R
};3 t8 V; z- I S7 r9 C6 \
2 {/ K+ `7 r- }/ p l. o. S, Z# c4 D" ~
// Dummy Implementation to be used when no other implementation is available- \! M4 E. V" p; Q
class CUPnPImplNone: public CUPnPImpl
- B- P( g8 d* ]" W6 |# ]- X3 K" `{
4 O8 r2 S- {/ u' G: j% i& Kpublic:
( W6 Q( O, v2 q3 a# E virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }
5 D5 K: {3 [' r- A" y virtual bool CheckAndRefresh() { return false; }
" u* u" N. o8 m virtual void StopAsyncFind() { }
8 M- Y0 J# Y( a0 x; t virtual void DeletePorts() { }
8 ~2 i3 g; F% J. d0 T virtual bool IsReady() { return false; }+ Y* F5 r# _5 ~6 H7 F" ~
virtual int GetImplementationID() { return UPNP_IMPL_NONE; }
& p0 d1 D5 W% E! W};
4 d3 x8 ]( Y7 v$ ]& K1 E g7 ?
$ k/ D9 @6 ]' |( h) G3 p2 H! l6 j
/////////////////////////////////////
" f1 G6 N ?1 {" T6 [- M7 q//下面是使用windows操作系统自带的UPNP功能的子类8 l9 s4 q% l) E4 f* m
! ^9 v; `/ W4 L3 W2 P0 z4 {
& Y; N: v1 q! E3 s) c#pragma once
9 k! ~/ }" F ]2 |) h, [#pragma warning( disable: 4355 )
4 m9 w7 D; ]7 `& ~2 Q; M) D: g) m6 M4 c6 [
: \2 w* r4 D8 b1 k
#include "UPnPImpl.h", M' G1 |; o7 p1 }+ X
#include <upnp.h>
$ Z8 D( v1 z0 P" L; L#include <iphlpapi.h>( p! k" |: c- A& g2 Q: |
#include <comdef.h>' t' B: Q% O+ ]: m
#include <winsvc.h>. F! q8 {2 j6 i2 N6 x
6 w. U% M, ~$ Z8 F' s; a4 Y
/ Y, h5 F S' O8 ]# R#include <vector>3 s, E) y7 v1 A4 C/ \" v
#include <exception>6 Y5 W) `& O5 @1 F
#include <functional>
4 _8 y" u, ?+ S; p4 w5 a j& Q. G- j% a/ N! W- A/ d
/ Q$ N$ x: k. \$ U9 a& w) N, o# R% h) @3 L; l- I _
* w8 A* a. h7 |& p5 \3 j( qtypedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;
6 n. |/ ~! V- etypedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;0 t! P. e! F8 r( D6 Z3 D
typedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;
3 \) R" _" T1 j+ Ctypedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;
6 `5 ]! @- x) `, H5 n% Z W0 Ptypedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;
) l% c- W3 A$ d: N `! ~typedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;
8 G6 b2 m* f5 ytypedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;
; @% |* p1 W7 [1 J$ M+ {
& ` h' V3 [7 B: t& x* Y% n5 g" f1 [: v0 Q
typedef DWORD (WINAPI* TGetBestInterface) (
6 M- M6 {6 b" D' R9 L7 g& q IPAddr dwDestAddr,
7 T. L1 [ L i% u: D% l PDWORD pdwBestIfIndex' g8 M% Q0 O5 E% V ^* V
);& R, h e( ~7 I1 ^ x
9 |" x% M# k p( ^3 L1 B7 e2 @2 N* }6 H: e9 s% U6 I
typedef DWORD (WINAPI* TGetIpAddrTable) (3 W$ G8 B/ ^+ k( |: x m4 @
PMIB_IPADDRTABLE pIpAddrTable,$ m0 E7 L" i0 F- T+ D
PULONG pdwSize,. P) @1 K1 g" S: q% J, Q
BOOL bOrder* N3 Z& }- q: i6 W; R
);
0 c9 N; G4 i" G
" ^7 {* B1 { l: G! Z, V' D' `4 F; [& {6 Z3 V
typedef DWORD (WINAPI* TGetIfEntry) (* W* [2 z& m5 e
PMIB_IFROW pIfRow* m8 v: F; C- o, o7 f A
);9 r L3 Q6 \7 d% o5 W, s1 F/ G
. U5 Y$ H! o) j* C
$ m# m( y' i3 `4 S5 QCString translateUPnPResult(HRESULT hr);
- J |- {! x9 n% E+ hHRESULT UPnPMessage(HRESULT hr);
8 m) l* M) O/ I$ M% w r4 \+ g+ B( H, ]' v: _, T! K# j3 H
3 W* g& B# ^ c
class CUPnPImplWinServ: public CUPnPImpl
5 e4 f- c1 b9 U1 C% Y9 D% V6 s{
/ W0 j! @% G# J5 o7 M( ~ friend class CDeviceFinderCallback;0 V' R7 f+ ?1 Q; {6 l" H
friend class CServiceCallback;4 M; F6 U( U6 }. ~6 c
// Construction
. n+ J0 j- n5 Bpublic: W' W& I" y: L/ Y0 x
virtual ~CUPnPImplWinServ();
# o5 |$ W- U8 B6 h* o9 r CUPnPImplWinServ();
) B: M, j: o( O3 R a
z( q* T0 q- t4 }, Z8 T
% ]* V+ E+ G, e0 {/ @8 z- s# { virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }
/ m/ x0 B; W/ q T/ |- q9 W$ w virtual void StopAsyncFind();( D9 k6 q- l$ X, J* P! W
virtual void DeletePorts();$ x* i T" I* @' `& U1 ^# P/ ~: z
virtual bool IsReady();# C7 ^9 g! v: `
virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }6 h! o9 Y! Y: q/ c S. k& A1 W
+ ~! h y& E; N* L1 ^. F
! w+ s8 P+ d( M2 E5 p8 Q // No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc) G, ~$ H/ I* L! y6 x. l& p6 G8 _2 g
// the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later2 u' w, M" b8 i9 K0 P/ m+ ?. F- i
virtual bool CheckAndRefresh() { return false; };$ s" w/ q! d6 p5 T
# T$ E! W! h8 V6 I' Q' a8 @5 M0 D
; V3 a: ^3 ~# ]- n! l, f
protected:* q% b/ ]8 a, a0 `
void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);$ [' `5 N6 T/ y. N+ O2 t- f
void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);
0 m4 b" p6 X8 N1 e1 \% q void RemoveDevice(CComBSTR bsUDN);
) I$ z/ b& P% g* j bool OnSearchComplete();
~, q- z0 E5 A) I void Init();, \; M/ m6 f* i6 j w* h( O) U9 }
+ |; t$ n8 Y9 A; b# l) r
+ @; m4 U* v" E( f1 `9 {
inline bool IsAsyncFindRunning() 3 p0 \9 D* x7 k
{- `# S: d6 ]; |9 K T. t2 l% F9 ^! R* n
if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )
- \4 {) J3 L& M6 x7 V, v8 W! j {+ k6 A& N& {- u# s9 N( G/ J7 p
m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );
& b+ w! A9 Z; {9 M l% { m_bAsyncFindRunning = false;- M! f) X7 X' {, Q& S
}/ V) G6 Q3 e1 v. G
MSG msg;" j9 ^' g9 w- R" ^
while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
% f1 x$ _- e! F8 S/ C1 I9 U/ p6 x {
F: ~3 z; f8 W: }7 C% m TranslateMessage( &msg );. v& c- v' i) i" D6 c
DispatchMessage( &msg );% c. H! c4 Q9 m
}" f2 z8 N: O8 {8 I
return m_bAsyncFindRunning;
5 i' E8 u6 @% S1 Z }! s6 F5 w' o* Q G% n
S5 ]* s2 z/ P, s+ H6 T2 y" ^( }) g4 K, [ c5 z# h
TRISTATE m_bUPnPDeviceConnected;
7 B2 N3 \! {8 Z6 X4 @+ F, F' M& o g5 z R2 F5 s0 W3 @- @
" x6 M2 V8 G! p( y# u4 J4 N# S0 I! S
// Implementation
- b9 w: n3 Z c8 I, {3 c // API functions
# Z* R; d$ [1 n6 I# v SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);
E7 r! p+ M' }( a+ o( Z SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);5 O% t: K3 g% ]1 s5 V
BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);
! H! J( b/ L# M f* v! P" L# Q BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);
2 C; e1 i+ R5 [ BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);- y9 W7 T0 y8 U* Z/ |5 }
BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);4 C# {9 j; O8 K
3 d% J$ S# X% u+ @
* c* a% @% o2 T+ n/ L+ ]: e; O
TGetBestInterface m_pfGetBestInterface;
3 _6 T0 k2 w3 ^0 q# V TGetIpAddrTable m_pfGetIpAddrTable;
1 R5 D/ x1 { W TGetIfEntry m_pfGetIfEntry;, T! Q% R( M/ y5 {" a
, d: O4 G% J8 e" b+ U9 g
. }) S5 ~; ?0 j* q static FinderPointer CreateFinderInstance();; r$ ~( I H# ^* u4 r0 ~# B# B
struct FindDevice : std::unary_function< DevicePointer, bool >
0 F5 \% `) B. d3 j& Z+ s- M {4 s7 k+ @. k5 X3 y0 r) Z' r
FindDevice(const CComBSTR& udn) : m_udn( udn ) {}6 b4 Y8 z# t9 C
result_type operator()(argument_type device) const% s* o; _0 b' S
{2 [0 D- w' A& E* [$ |" b9 I- @
CComBSTR deviceName;
1 i P! b0 B& q$ {: e HRESULT hr = device->get_UniqueDeviceName( &deviceName );' M$ b1 q1 O& S
0 z d( U+ M) D9 `4 H
0 k2 o3 ?9 B+ Y6 \0 c
if ( FAILED( hr ) )
- X1 p. m" }( j& p return UPnPMessage( hr ), false;
) O1 }7 i5 e* z. [, X9 Y) j k w' s, n1 H4 a5 v$ [" C$ J
' e9 C+ z7 K: H6 x& x return wcscmp( deviceName.m_str, m_udn ) == 0;
% P" d5 `% B& \ }
! C: Q- }: y5 C1 N CComBSTR m_udn;0 h# `3 o( y1 I% `' D- Y
};: M! k8 V9 u! j* k) g$ O
8 B( j$ c0 [( ~$ p4 w4 S* A void ProcessAsyncFind(CComBSTR bsSearchType);
( q2 }! F" n! Q HRESULT GetDeviceServices(DevicePointer pDevice);) L; A/ V, X V: H n
void StartPortMapping();& o* k. Q2 I) e5 g; C
HRESULT MapPort(const ServicePointer& service);+ z; M) t% G) ~5 r. @( T, ]+ G* K
void DeleteExistingPortMappings(ServicePointer pService);
C* S; L+ \* _! a' H void CreatePortMappings(ServicePointer pService);1 B* z! _) E& I' x' X& I* I2 U
HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);
9 v% e. D7 F/ C% L0 y; O' H HRESULT InvokeAction(ServicePointer pService, CComBSTR action,
p: V7 X8 v; m' ~ LPCTSTR pszInArgString, CString& strResult);' J# i2 m* Q: b
void StopUPnPService();9 N& I$ N4 w9 w
8 z t, s- `4 ?6 H& }" M. J' [: D4 j+ R* x" u3 q9 w0 \6 s
// Utility functions
% t0 h# ^- A' N+ z" j) L HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);. `7 c' t/ D# [( D' ]9 N) s
INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);
) D4 s1 v9 g" E o, b+ X INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);' [; N+ }9 a# C7 Q
void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);
8 S% r. V$ f/ O2 k9 R/ n% @' a HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);
: i |& b, P3 ^+ ?1 j HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);: W% R2 e# r c9 _6 a
CString GetLocalRoutableIP(ServicePointer pService);- x6 V% F( E( P6 P9 [
$ X- z9 F( q9 `( y% l4 H9 }) Y
/ D2 I0 C `! l! V ]4 m8 ^// Private members3 g* D1 ]6 V# F) I; e
private:
; |5 i. ^0 P4 E( Y C' y: R3 f; ~ DWORD m_tLastEvent; // When the last event was received?
' h6 [" v$ n4 k" Z$ z' {7 N std::vector< DevicePointer > m_pDevices;) b' D: h8 N# P6 F- k' L
std::vector< ServicePointer > m_pServices;( M. L1 q J$ N+ ?* Q* ?+ @' b+ Y
FinderPointer m_pDeviceFinder;
8 M: }7 j( l# R; I$ P DeviceFinderCallback m_pDeviceFinderCallback;
6 |; V# j; _& s; k( V ServiceCallback m_pServiceCallback;
+ }* ?6 q: b% [- e
. L# w/ U5 K6 Q' Q$ X0 ~( z, }6 D( A) {; y5 C* @2 I
LONG m_nAsyncFindHandle;
- ?) r* T/ P1 w, `. a2 \ bool m_bCOM;
) _- b& S/ u/ t0 l9 G bool m_bPortIsFree;
9 a- e& g. |5 Q; I9 e CString m_sLocalIP;+ X% G$ k6 N& R' i+ e5 w
CString m_sExternalIP;
, e9 b \, D6 K6 ^; Y4 o8 ^/ y1 F bool m_bADSL; // Is the device ADSL?+ r" v, T x- p( B. S ?6 y
bool m_ADSLFailed; // Did port mapping failed for the ADSL device?, |. U) ~, W: V2 m4 V6 a
bool m_bInited;3 @. M! i. D& M2 B& p4 z$ E+ S2 ^
bool m_bAsyncFindRunning;
* f& c1 g# }( T C- a- x$ B HMODULE m_hADVAPI32_DLL;
' p2 O6 X6 v H' U2 L( y) a HMODULE m_hIPHLPAPI_DLL;
/ t1 |5 H+ l+ W/ ~" h bool m_bSecondTry;
# D$ x7 M8 }0 M bool m_bServiceStartedByEmule;; n: G& S, P% W
bool m_bDisableWANIPSetup;7 ^) D% s; F! z0 W/ Y2 B# n& k
bool m_bDisableWANPPPSetup;
I- F6 ^6 e/ t
% v9 ]7 J; L' V- ~9 ?7 K' A4 O
$ K5 \$ P$ r M2 k};
2 G" J. j! {* J9 m; ]7 ]# u- ~
! {/ Q" w% P. Q% F F8 R& L% C) H" {- ~# U" c# l. u
// DeviceFinder Callback
: w7 o: [+ E+ A! ? M% ?( Yclass CDeviceFinderCallback0 Q' |, F! B' M* q3 o
: public IUPnPDeviceFinderCallback) G- Z3 S5 K9 C5 v9 [
{
4 p! e8 e# r4 _: R" k7 {' F' `public:
* i5 K' I$ s. a2 }9 ^ CDeviceFinderCallback(CUPnPImplWinServ& instance), ?( {* V+ O; W. y: ^% j( j; @1 o
: m_instance( instance )
$ A7 v1 u' X; y7 I' u3 [7 N: M' X { m_lRefCount = 0; }) @# C" ]% g d) T( K4 H5 Y
* o! Z% u. V; ^& |. o% G) P. ?) @9 q1 \7 O+ L: y- O
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
1 y$ r6 O& h: B STDMETHODIMP_(ULONG) AddRef();
0 Q3 H9 @6 ~! X4 Q1 p- N: K STDMETHODIMP_(ULONG) Release();0 {" D0 @! D1 l
7 _' W. g! C1 r) o
) p* u$ k1 e: {# o& H6 ]+ j! ?, N& n// implementation
: i* j o" f. sprivate:. J. N: d; a7 h
HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);
/ x* r6 f- C/ N8 X HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);
X" o# O$ L4 c+ _, r% d& o w HRESULT __stdcall SearchComplete(LONG nFindData);
& ], @. t5 E4 K2 W" I3 D, S7 P- [! S3 G$ u, q
' t2 S& z' r8 A A( {6 G; j
private:* T. u. J& Z- s, X% s
CUPnPImplWinServ& m_instance;
7 u) z/ h0 q& |( v/ f LONG m_lRefCount;
9 p9 _- B& f! x" r: [};- A; O" R/ |& f# a
4 y% E, i9 [2 q6 K, ]
1 F/ @- g6 J' Z# A7 `// Service Callback # H6 L# C/ y$ O& V4 Q7 V. X5 |
class CServiceCallback
% o2 ]9 k: c* F$ e: L1 W& z3 H : public IUPnPServiceCallback6 }( l) X, e% H" i# s
{
! @1 b' i" p4 I& W# zpublic:
% L! O5 F! ]+ X, L& z; V6 _ CServiceCallback(CUPnPImplWinServ& instance)0 _5 C9 g) S' O$ B' i+ H4 Q! F
: m_instance( instance )9 `% t. u1 e1 V1 m9 G; ^
{ m_lRefCount = 0; }! t: v/ b7 \0 E; \
3 A6 h7 R- P5 I$ J5 {; J. k& B2 s
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
5 z6 l7 _+ [3 ` STDMETHODIMP_(ULONG) AddRef();+ y$ [; c" h$ x1 @
STDMETHODIMP_(ULONG) Release();( A" z# k9 W8 G @5 |& s
0 W' G, X" ^# A4 w' K& T1 u
( ^* U; Z- U( t: `& l( |// implementation
; U8 o- l! } p& m3 Iprivate:1 M. k; O M b1 I) i8 `6 O
HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);4 a8 ~8 |+ D" J# Q; w/ t
HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);# J. F' E5 @0 p
& s* c7 W( |, m9 q: F
c( t- g+ E" [( Z& H9 _) j8 Dprivate:4 d0 S: `, O! H, E3 T5 V; i8 E
CUPnPImplWinServ& m_instance;
6 x. R8 c3 W* ]; C# S LONG m_lRefCount;! u# k2 Q2 C( ^2 ?) t0 i7 C* l" a
};9 D6 o M* d( u3 z) }
; i6 g$ ?! S' V0 }% n* t0 c3 i; M# s; i4 ^/ k' N1 M& r; _
/////////////////////////////////////////////////; G7 j4 y% E2 Y) X N8 Y
8 d7 L1 q& X0 o+ g2 V# z i
7 P3 _* o& ]! h8 l3 ~, f9 k5 j, _使用时只需要使用抽象类的接口。
6 f7 W. {4 `1 B* C/ p4 a) @9 ?- ACUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID./ Q$ L `5 a# }
CUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.! B" i# \" X/ g r1 R- W
CUPnPImpl::StopAsyncFind停止设备查找.
( t& y9 y0 c! ^ PCUPnPImpl::DeletePorts删除端口映射. |
|