|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule,
3 F' B3 }1 [$ i) v4 t ]" Y& \/ o7 {) B( B6 q
& a/ F. I9 w# K* a///////////////////////////////////////////
- x+ f! j; Z+ @/ p* A/ a# `, T//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.9 H1 v6 E9 }: q Q
- s4 O: J/ u1 z/ H' D! ~& ?* T2 s
#pragma once
6 ^- b2 y- | |' \0 A$ k#include <exception>
5 a3 ]7 {& W; ]. B. ?# [0 E
% E# m; L, G4 V0 V: ?0 T, F, v3 b5 ?# j9 G( _
enum TRISTATE{: m9 X H& T7 }" F6 ` x' _
TRIS_FALSE,6 G- L: F/ Q( v
TRIS_UNKNOWN,
) [! X. q/ r7 x$ a/ l TRIS_TRUE8 F9 `/ v0 Z1 y# _0 d- W
};+ A. s" K# J0 ` G# W& K
6 Y. i: d# \) `" g$ u: X9 t( c, x# H; T8 h( X
enum UPNP_IMPLEMENTATION{
- w) D6 t: y* V# }8 w+ j UPNP_IMPL_WINDOWSERVICE = 0,2 j4 [* v2 ^) M+ ^2 o
UPNP_IMPL_MINIUPNPLIB,) d0 S) `' Z" _8 G
UPNP_IMPL_NONE /*last*/
) b9 q; t* Z/ x* P- H9 q/ \) Y};
! C. M, {2 h, E) y1 X" @) O
, u5 {7 l) I3 Q6 b. i+ ~. h+ t1 `* b6 |4 @8 ?, I( e
$ S# M. f, R. f4 `% v
& x3 [ H, u- V6 B! U/ U
class CUPnPImpl
4 q, d; P5 t' S5 y |, n) {; x{
9 z2 t* C( S9 m1 R/ |3 npublic:, u: H$ S8 A; \- q
CUPnPImpl();
3 I4 q! A/ Z$ ^: n) u O virtual ~CUPnPImpl();
- Z* P, f( e8 s struct UPnPError : std::exception {};" _7 {1 J: m- i' N
enum {
( Z6 i1 I# l4 [1 d$ @$ I UPNP_OK,( y; z+ \5 b4 e5 Q
UPNP_FAILED,$ f4 l a/ X* G( }
UPNP_TIMEOUT
# F; N0 N6 b1 H& s% i# q9 L };
/ Y4 [) ?- Q3 |% y% y9 D
2 r) s4 c6 s/ I* l1 y7 H! K' _5 V: b$ r+ a' a0 ~5 {
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;
( c3 H+ b, `7 H5 t virtual bool CheckAndRefresh() = 0;
" {* d6 T9 ^& B* n5 E( g1 s9 } virtual void StopAsyncFind() = 0;
! s, t" }# x4 g, \ virtual void DeletePorts() = 0;" v& G) R- |% t/ i
virtual bool IsReady() = 0;
/ C+ P2 S" \0 T# D% T5 K virtual int GetImplementationID() = 0;3 d1 ^; M6 O9 g# K5 x) l: C
- @2 v2 t+ h J* T: S
void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping* L2 @4 u8 j6 p- T, t7 ?
3 j9 e$ C# Z% o' m1 O6 ^" R( j" d0 g, L% m% k1 m
void SetMessageOnResult(HWND hWindow, UINT nMessageID);
1 P( ~' V* n, ~6 D" ^ TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }3 N5 s, V$ S( `$ y% X& B
uint16 GetUsedTCPPort() { return m_nTCPPort; }
6 X& ]2 _$ f4 R% N uint16 GetUsedUDPPort() { return m_nUDPPort; } 4 u: a! F6 E' {$ C! z
; n2 {: z9 x+ k6 r+ ^0 n
$ m9 J- T+ |" F// Implementation. k4 A7 |) A5 F
protected:
+ H. x# U( I2 `5 e3 [4 _& O! a volatile TRISTATE m_bUPnPPortsForwarded;/ c! |$ d6 l4 w% g* Y/ `9 A" v/ s# F
void SendResultMessage();# h8 R: C7 Q; z" G- u" s- b3 q( E
uint16 m_nUDPPort;( x% p1 Q/ C# M) T6 [3 f# @4 R1 a$ B
uint16 m_nTCPPort;
9 [6 c' u7 Z8 Z* @4 G8 P uint16 m_nTCPWebPort;/ m4 S( @: o: X
bool m_bCheckAndRefresh;
! V" W Y ]4 o1 ^( Y. I! _3 e3 O n7 E! p
7 @& l( e+ F0 j& G7 Bprivate:
* ]* o- D. C3 v/ G$ N3 Z HWND m_hResultMessageWindow;
- y) D( K0 y0 x: b/ b UINT m_nResultMessageID;
2 X8 p+ v# A' Z" X3 N6 p# Y8 S- y: [4 @9 \
0 S$ G- }5 v/ P, u};7 D. i& ?4 ?/ B; B. Z6 q; @' U( C" \4 u
' a: K& D5 `6 f+ y& D' Y8 v n, G# v6 }( B( d
// Dummy Implementation to be used when no other implementation is available
: K4 | i& g" M3 Vclass CUPnPImplNone: public CUPnPImpl
7 c2 {; Y; j- ?; r/ y{$ S m3 w' d. \
public:! O0 ]- y9 m" G. H
virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }
; x4 l# ?, i5 R virtual bool CheckAndRefresh() { return false; }4 o1 p6 Q2 O6 N* q2 j) E
virtual void StopAsyncFind() { }
% d& O9 [! K3 i, h! {/ L. q virtual void DeletePorts() { }5 E9 F# `7 c" `, X/ V m5 M0 N) S
virtual bool IsReady() { return false; }* K: {& P+ Q; _/ a+ E7 R0 H
virtual int GetImplementationID() { return UPNP_IMPL_NONE; }
! P; P0 O+ X& }% p+ k, D9 u( H};
5 H; d% [1 ~" ]# [5 J3 F5 B; ]. C7 y0 E3 ]
, i8 K) D, G4 t1 Y, N# ^/////////////////////////////////////
+ R( x1 u0 d3 U$ w//下面是使用windows操作系统自带的UPNP功能的子类- n0 g! a0 o0 n) g$ _
( [ Y# n" S8 U" ~/ o& U
$ r& r* f- }$ k
#pragma once
& L+ C- C. }% @- W#pragma warning( disable: 4355 )) |! g) s* [* ~
! ]% L0 k! y p# I2 Z* n! {
% P4 ?. \0 _+ ^+ D0 Y" U9 ?, j
#include "UPnPImpl.h"' Y* ]3 f8 t, r4 u0 Q
#include <upnp.h>
( g2 m! @. j/ J8 b( O#include <iphlpapi.h>
+ J# E3 b8 O5 T#include <comdef.h>
# P- a& U* b9 Y#include <winsvc.h>5 K/ L& S: j. p
7 P1 O2 ~% m% O2 Q
* ^5 |+ o% r3 ?#include <vector>5 @# l* z; S1 f# A
#include <exception>
: @7 A7 b4 \ L% u; E* u% N- d#include <functional>
0 K$ k& w& R: p* g* ~8 U9 { P9 I
' |4 T/ r* j1 }; S- b: S! q0 n7 r" `5 |7 W9 e; }
; Z+ m; u( T# P3 y; W% e3 t
5 `. E/ o. g* A7 L8 Y7 {) ftypedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;
) b0 F5 E7 c \. [typedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;0 w0 Z" A. n" o# {
typedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;% ?/ _5 O: o' r- q' `
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;
- m. {" b- m. P8 _; z( stypedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;
9 H6 g j, ~. H9 S: ctypedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;
# ]- q% m# h2 j) c8 P$ t! gtypedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;6 k) ]5 W- ~7 g6 q
8 W f. S2 F& v3 p) d# K7 u" W& p$ ]- Q+ d
typedef DWORD (WINAPI* TGetBestInterface) (
4 X) n) Y$ H5 u8 L( [3 i$ ~ IPAddr dwDestAddr,
9 R; u' c6 D& s# V8 X PDWORD pdwBestIfIndex; G" s/ x2 T% F" b$ o) X+ r4 [# d2 h
);. I- T7 ^. g% ~% L# o# _
. G6 i0 K' j% n6 N/ E6 g. t8 q( O2 n
# I8 E8 m4 q: L2 I! S1 ~0 u( Ntypedef DWORD (WINAPI* TGetIpAddrTable) (* R: S# t+ j) B' C' J
PMIB_IPADDRTABLE pIpAddrTable,
& u) N. Y2 I9 ], T1 f, m) e PULONG pdwSize, Y' D' C' L9 M
BOOL bOrder( d0 p+ g# l2 [1 W, o
);% _* {, q% l' t6 E- b9 t8 |$ U
+ u" S" h ?( Q: s: G( ]( ?
) C: U2 e4 I# r2 @1 Y
typedef DWORD (WINAPI* TGetIfEntry) (- _. B8 z' o3 Y# X) F
PMIB_IFROW pIfRow
0 m1 S- n# k* Z% S);
' E# ^( U: V9 N) v4 t& f8 Z, |* B( p) ^" k7 S& v
& Z$ j. y. W' S! y" m0 ECString translateUPnPResult(HRESULT hr);6 n; H9 H8 ]/ A
HRESULT UPnPMessage(HRESULT hr);# s5 W6 f" }) c. y
$ g& I6 A7 f! I% J) U
+ I0 t/ |7 \% Gclass CUPnPImplWinServ: public CUPnPImpl
7 i- [# X# s H9 n, ~4 ]{
2 ?1 v2 L+ d e: X0 G friend class CDeviceFinderCallback;9 E) a: r9 h9 }
friend class CServiceCallback;
) l/ J8 L9 a2 R) i// Construction
# r" B- ~! E E1 v8 R% Ypublic:
' b. j$ _* }# M$ _ virtual ~CUPnPImplWinServ();- ^) w4 d7 |/ k+ `2 O0 Z3 s5 _
CUPnPImplWinServ();7 x( R6 h* X* c+ i) y3 h
$ p- y) J( ~( c# |6 ], l, B$ K2 u
2 }& d' I9 p9 T+ ?0 u) L virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }: R3 b) z1 U) f# O; R6 d
virtual void StopAsyncFind();7 m& O6 \& u% ]- S! [4 J4 Z$ S) G5 T. m
virtual void DeletePorts();
' U0 ^- g7 P3 O J+ W virtual bool IsReady();
. N2 N8 l5 q% a* d5 i virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }+ b+ b4 T9 u6 S1 i1 p' a4 a
3 L7 L8 z8 I( R, E: b+ z- Q7 r- m: L# O7 e. s- o& ^7 E
// No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)* _: ~5 c( d6 d$ x1 U4 S/ M+ i- z0 e
// the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later
' l2 k" ]8 i2 E6 g' C virtual bool CheckAndRefresh() { return false; };
+ Q# u8 O- }4 E8 E' Z. O) \9 u0 q2 A
1 O/ w Z; d* ~& X$ q3 eprotected:. l( J5 Q" N) z$ x
void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);( e. U4 {3 X7 k$ N4 b
void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);' E [) S/ _5 N4 P0 [
void RemoveDevice(CComBSTR bsUDN);
! T' N' |; D9 ?4 L/ U9 z, v bool OnSearchComplete();" z( U% ]& q' i9 `' r& T
void Init();
+ E* T; e' d& E) U+ [, L* u( n
* m% |3 ^: z; x5 m2 T, z, m2 r% l+ I$ n! H A9 B# R- e
inline bool IsAsyncFindRunning()
. D- h' d: ~ K# U {" r( s1 X f z7 t; x% N/ J8 l
if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )
# `4 @; Q; |- S5 G6 E" y {# j# B' p, m& N& c
m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );" b# B) z4 p2 W! O; F* F; ~; v
m_bAsyncFindRunning = false;& Y% h5 q. Y# L# [
}9 B% B# i+ `4 T% d6 l& F$ _; W
MSG msg;* x8 O/ a" S1 O8 f) b
while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
7 b1 L* D) D$ f; N, A {
" q/ `+ Z6 i& s) q D5 L) a8 a. U TranslateMessage( &msg );
6 b( }5 `- q4 B' I DispatchMessage( &msg );
" K% a5 f) @/ _ }
9 a4 G9 O: \8 n5 M6 B4 s' d) T: N5 { return m_bAsyncFindRunning;
5 E9 ] X. r! l1 K9 f4 V2 R) F2 } }; |- g& Z4 o0 _" ]- |
0 C0 L( g, B' P
1 d9 ]% B7 N0 q8 O
TRISTATE m_bUPnPDeviceConnected;1 C, x0 d2 p# y, D4 @7 Z0 P$ C
( z$ ?% H' X- u# d. r1 S" }; @+ _# `- `/ [
// Implementation
/ k! k% K% t/ t( h8 V& b; ^9 n // API functions
T9 y/ d; Z1 N# y9 u, p/ U SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);' I9 k) a. v- E
SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);
1 ]& L! f/ J. o0 z' ] BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);
. n7 k: S" F0 b J9 s- R& i" q& }5 [ I BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);
( R+ W" G- @! x0 N0 g; u BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*); i1 Q+ o9 C/ Y
BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);: `$ D/ G% I1 a3 P4 [9 w* k
" P# f& P9 |- X! o
* F2 C9 B# Y: |
TGetBestInterface m_pfGetBestInterface;1 L/ N8 g9 E% d% |! i
TGetIpAddrTable m_pfGetIpAddrTable;* G: P' v/ w) K4 K' w
TGetIfEntry m_pfGetIfEntry;
' S5 J/ G' t* e: \. |. o! P1 r4 ~; J# Y% |* o \5 }+ B
( T$ b9 @- I5 @6 @3 {
static FinderPointer CreateFinderInstance();
5 L+ x8 e9 R* i+ a6 l& ~# w struct FindDevice : std::unary_function< DevicePointer, bool >' |1 `' [7 E' E4 [7 {3 O @7 z
{
! G. F4 a7 m' A/ J" s, c$ f FindDevice(const CComBSTR& udn) : m_udn( udn ) {}
" v% u% Z& i6 o* A* c result_type operator()(argument_type device) const9 B2 Q& Y* r5 e1 ?! W) X4 \1 U: L
{
( z/ @1 I+ U) T, I' ]- T/ B1 R CComBSTR deviceName;
* Q: v5 e8 q2 t8 e4 | HRESULT hr = device->get_UniqueDeviceName( &deviceName );8 q/ O% q. W; W+ e9 P5 x) O
$ U1 y$ Y( t5 h P: j# C! t+ J! i' X" |
if ( FAILED( hr ) ): y ~! @- S: Z% H* e
return UPnPMessage( hr ), false;
: e3 h; ?& ]' x9 i0 Y" q2 P( ^- l' W. u
( l% M6 [# \% [! Q& f
return wcscmp( deviceName.m_str, m_udn ) == 0;# b! o" V( o4 l8 U0 i( M8 `
}
4 t6 ?: m* j+ P/ v6 B; @ CComBSTR m_udn;2 Y9 L; X [4 b) Z7 S1 P
};
' @* ~& P2 @9 q! v9 x; N6 y$ N# t* ?/ J 1 N1 U% Y7 `; D
void ProcessAsyncFind(CComBSTR bsSearchType);
+ z, m' I5 t' `3 W/ x, o HRESULT GetDeviceServices(DevicePointer pDevice);
0 Q2 v0 [) O1 S) c% ?4 O5 E2 B void StartPortMapping();
, U& _, o' Y4 w- m* j HRESULT MapPort(const ServicePointer& service);, @: K: _6 i9 e3 p. I1 m3 T
void DeleteExistingPortMappings(ServicePointer pService);
) M0 W0 m1 X6 d) s( z void CreatePortMappings(ServicePointer pService);
6 a9 b' {# J. S( x HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);9 \# X+ A5 t* @5 w6 m
HRESULT InvokeAction(ServicePointer pService, CComBSTR action,
+ B+ t; |- M7 I5 R9 A' q; d) l' S LPCTSTR pszInArgString, CString& strResult);, H; Q p3 e1 u; ]: F
void StopUPnPService();. U% I* p8 z# t' k1 L; V9 \/ ?* b
8 r& P0 k. c l }
- G1 ~( ~5 C4 j6 O8 o // Utility functions
/ d! D6 j3 p; X0 ^# S" d K6 ` HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);
2 h# B9 X8 z" J7 ~, b3 g0 E INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);2 B- _5 G0 [7 c6 E# r
INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);
5 d; A: ]+ E8 g/ v8 m) v0 X, v void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);7 g' A/ \: d. ?" b6 U" c @" Y$ G
HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);
0 }7 l) v5 W) z( U HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);
8 l3 S. x6 i5 {1 D+ E7 v: ]' ]) J( H k CString GetLocalRoutableIP(ServicePointer pService);
) n) b2 d* g% t% d% d2 I) w/ X+ X
2 H- m% ~- m% X0 k3 [
9 B1 D2 E! c, r4 O' e// Private members$ g- T1 k* J. J1 D0 N3 p
private:( O$ j2 F S+ `. h. H8 c
DWORD m_tLastEvent; // When the last event was received?4 y) c2 E- C- D
std::vector< DevicePointer > m_pDevices;
. K! c% @1 Q/ L( n) m k6 P std::vector< ServicePointer > m_pServices;- b5 I) I" ]! q9 K/ M
FinderPointer m_pDeviceFinder;$ N* P4 ^. U; j% s
DeviceFinderCallback m_pDeviceFinderCallback;3 Z/ G# t: k0 [2 J! ]2 G
ServiceCallback m_pServiceCallback;
$ y9 h. u: Y& s* t5 W- R+ w# C' J0 x6 N# W X- @6 A2 q- y X+ A$ C
8 U3 e7 p+ j8 X' M/ E LONG m_nAsyncFindHandle;2 k! ~ ]" A7 \$ x8 q7 f3 _
bool m_bCOM;% q! }: B/ _/ R- m% W; m
bool m_bPortIsFree;! [2 O( Q1 O$ H3 g4 c6 R5 E
CString m_sLocalIP; f* c7 e& o. V. i; w$ { q7 W
CString m_sExternalIP;
& k& d' J" `: g3 Y( H* f. ? bool m_bADSL; // Is the device ADSL?. [5 Z+ v' E3 _
bool m_ADSLFailed; // Did port mapping failed for the ADSL device?* x8 c+ k# X( N$ C
bool m_bInited;7 u+ P9 H1 @8 N M1 t6 D
bool m_bAsyncFindRunning;
7 ]$ h( }; B% r4 ?5 \# _, B. F HMODULE m_hADVAPI32_DLL;
# N/ W5 k, U. S+ T& ~4 v HMODULE m_hIPHLPAPI_DLL;# j0 B1 }- {) z& B: e, ~6 G0 V
bool m_bSecondTry;/ X% \" L* a0 C& h9 U5 L
bool m_bServiceStartedByEmule;" v2 a9 J( Y9 U) {: |' x B
bool m_bDisableWANIPSetup;' {- O' Q7 E8 q5 O# Z
bool m_bDisableWANPPPSetup;/ Q) r% e0 ~5 L V( ~
+ H' H+ c i, e; [' @& b2 s9 `
( n8 G2 e7 d3 y1 g
};
0 H% x# }# E0 {" h
; [3 G1 w9 p9 W f- e. }# T8 k* O1 [' \' ?- K+ M: V8 K
// DeviceFinder Callback
9 @6 o$ D7 v0 E' }3 y8 Qclass CDeviceFinderCallback
7 f2 \* _, f2 y, B : public IUPnPDeviceFinderCallback
7 Y* Y( D* J8 |{
5 \: f& r* o5 m# B1 S) Fpublic:
4 q0 s! o @" H' r B& v2 D CDeviceFinderCallback(CUPnPImplWinServ& instance)
- F: P" _% k2 u$ B9 x1 K : m_instance( instance )7 e% I2 z! D2 @4 f! S1 _5 z
{ m_lRefCount = 0; }2 Q) j+ O( {7 d8 \6 I
* M8 V( X5 a T+ }4 h J! y2 E4 w4 E
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
1 H# g$ w( d4 t STDMETHODIMP_(ULONG) AddRef();" _: s, m. B" [ O+ z1 f2 ~
STDMETHODIMP_(ULONG) Release();7 ]9 H1 \$ I1 i
- [2 p, Y [. O5 N' u
3 d2 r8 z/ i# y# Y// implementation
/ b+ b3 Y$ e. U) ^# V' `2 oprivate:
# |1 [% O, ^( X" a- W HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);
/ x) O8 u2 `1 j HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);
C( k- v: m! X& y1 j2 G HRESULT __stdcall SearchComplete(LONG nFindData);
+ ^4 J1 `: Z0 e! t" u- C: }- f% V# q. H6 \5 q8 p5 @2 ~0 }9 W) |
~5 D7 p8 l6 i) kprivate:
7 J8 `) s* E# p$ O$ B. x. o6 l8 @2 n CUPnPImplWinServ& m_instance;1 @' [" a8 }9 ?( A/ \6 O
LONG m_lRefCount;
' t5 ^/ a5 @/ j" }};3 K* F S" r; }+ S- D$ c
5 ?4 u' d) j6 h6 P5 R$ a
9 Z6 \3 [$ \. {: K' \ ?// Service Callback
$ G: |/ F8 s9 I! R2 A. zclass CServiceCallback% J. s0 l1 c4 \' v( K
: public IUPnPServiceCallback6 p+ A1 l' O/ H9 d) `( j8 a% E3 p
{9 c5 Z1 U1 w7 u
public:1 }+ U3 o5 g4 C# e& ^, e9 k5 m
CServiceCallback(CUPnPImplWinServ& instance)
1 h' V8 [1 _& K, E% `0 ^1 _ : m_instance( instance )' {0 ]2 t4 F; J4 i1 a
{ m_lRefCount = 0; }
7 y. ?2 C9 p. N( g |- ?. |
+ ~8 K1 |; b0 A; `0 `, _" t. W# C STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
0 m [: T5 u0 `# ]- h; o$ v STDMETHODIMP_(ULONG) AddRef();
$ |# l; S o3 G2 b8 E STDMETHODIMP_(ULONG) Release();! D. B7 ]5 `8 h9 Z" M
" z8 D5 D) R& A! S1 U5 _, W; }; S2 `# ]) ~
// implementation4 Y. f& O) [( C0 Z
private:
% [" C- k9 v. F3 T. B5 ^ HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);
, w6 U4 B% d* ]5 Z' v2 m HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);+ l( u7 h/ K- B: a
( L- l8 X6 H T' Y
0 s+ f7 S+ Q- M1 r; H9 C
private:( l& t [' t5 o4 e* A `/ ]3 K* S
CUPnPImplWinServ& m_instance;
4 s- s4 l2 b; U2 X& \% z6 K LONG m_lRefCount;
; f+ m+ c( |3 A1 J- u- l- }};
- H5 Q0 R) X1 y3 m) s h
9 W; n* n( y( w3 v/ F. e7 P9 d3 X# Y. E! a
/////////////////////////////////////////////////6 R4 w. b3 K, P- B
: J) J7 x. m; X' j# e( `
8 K6 s- v2 [1 d' M1 U使用时只需要使用抽象类的接口。5 S0 p5 }' o, v
CUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.
( t3 C+ w k5 D7 U1 lCUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.
) e6 l* k( c: a. [$ h- FCUPnPImpl::StopAsyncFind停止设备查找.2 n/ W# _: I+ z6 Z( k0 u2 J/ [
CUPnPImpl::DeletePorts删除端口映射. |
|