|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule,
# y3 G0 S) k$ w% p4 x; P' Z8 w$ [" S+ b: S9 d+ p* C* {5 j
# m9 @' y% {, u- T h3 q, x1 c# U
///////////////////////////////////////////
- p9 m8 i) r. S& T//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.
9 N# e6 f- j" p2 Z" S9 ?0 j. d O
8 R* F$ M, I4 V- Y: a; a
#pragma once% b# \" K$ g% z* ^' t
#include <exception>+ E0 I: _ E% A
8 \* R8 @+ R; s8 z3 f5 U# o# B1 F; m* I2 p U
enum TRISTATE{# }9 W% B3 y5 _' a
TRIS_FALSE,
/ Y$ `% u% x. Y. h TRIS_UNKNOWN,- J/ v, x. [: G4 V$ l3 K/ {
TRIS_TRUE
" |! y l: A' m6 r5 g};
8 Q& o6 y; }& ]; k
: t7 I9 M, ^; Q* m! C( h* K; O$ }, B6 B2 T
enum UPNP_IMPLEMENTATION{
- \* A) E8 Q0 p, j) ~* p UPNP_IMPL_WINDOWSERVICE = 0,
2 @) K% T# G% b UPNP_IMPL_MINIUPNPLIB," w8 ^1 K9 L i" [. g4 l
UPNP_IMPL_NONE /*last*/* d$ ~9 O+ \+ j9 ?' J7 {
};1 x- o* Q& [. b" E, R6 m- O
9 A8 u$ }+ L- U7 e( L* e+ A
- p7 V5 z' @) h3 ^2 J( V& k4 [
, o1 i1 W9 u# J# \; _9 Z
, O5 h \0 M: ~$ Z N5 U9 R Lclass CUPnPImpl
3 w' a6 b. w/ P* K" o; j( N" h: b{
6 C7 U( r$ ^$ l. Ppublic:/ V8 r ^( x+ y' ^- T: k& D
CUPnPImpl();
5 b' z/ ?! A5 d) l! v: a virtual ~CUPnPImpl();! c% p; C; i3 @
struct UPnPError : std::exception {};
J# d0 H0 j' b6 X& W enum {; Z% q1 \, p1 t! t4 `
UPNP_OK,
1 c4 J$ i: u0 M+ A UPNP_FAILED,; {$ t+ h- F, ^6 |
UPNP_TIMEOUT
6 q \3 M0 |2 K/ G! n/ C0 K };& N, l( V" g# R& ^' D
8 D" {6 V: f t0 q9 E* ?
' l" }7 `$ j( }3 P; x/ @/ v
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;
" r4 C9 r. X7 W4 V a virtual bool CheckAndRefresh() = 0;
# }" |4 Z( F) {- n8 [$ n, z/ ^ { virtual void StopAsyncFind() = 0;( f2 P9 p, x, S5 z& `9 I3 `& L1 h
virtual void DeletePorts() = 0;
0 H7 C9 {& T h7 |( X virtual bool IsReady() = 0;
2 P- u, A! M: S7 l" E virtual int GetImplementationID() = 0;0 m/ n. {2 e% X0 N' f
/ ^4 ?" @, x# v2 X0 X t void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping
; }; Q4 S' \' m7 x
0 \1 c* M9 A- A6 C' ]0 r! P% V* K# y2 h# M* h
void SetMessageOnResult(HWND hWindow, UINT nMessageID);
8 p1 J3 b, M+ k0 _+ ^: _: M! J. ^4 I4 H TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }+ }- d# N, S6 t
uint16 GetUsedTCPPort() { return m_nTCPPort; }
+ }' d3 S( f5 D. L+ A uint16 GetUsedUDPPort() { return m_nUDPPort; } ! V5 ~7 }. i% E8 z4 Z/ H( a
2 e/ r# Q7 L }6 h7 N
! I0 p8 Z, p! J& b0 s% ~0 k' ~// Implementation
/ K) b+ I) }+ `& `protected:
! v) K) b+ [* D0 @ volatile TRISTATE m_bUPnPPortsForwarded;0 |, c$ ?) X1 Z4 o/ Q
void SendResultMessage(); T. E/ C r. c- j: O: u! k g
uint16 m_nUDPPort;
" v, ^# \ O6 ] uint16 m_nTCPPort;/ _* S% Y/ l3 I a0 G
uint16 m_nTCPWebPort;* E2 d1 R2 i4 G4 t7 K3 L
bool m_bCheckAndRefresh;) }! M3 z6 e. B- b9 U v. H
5 y- D' R7 W* c# t. C+ }- F
0 r1 |+ N$ k4 n: Wprivate:' B! b- T9 Y* `0 ^$ p1 C* f0 j O8 R
HWND m_hResultMessageWindow;( b5 m/ O1 M* T/ ]
UINT m_nResultMessageID;
4 z' T1 _, S" s9 F0 e* m( h; u3 x% S0 [( U/ |% s
+ j0 N0 }, x/ P
};+ U& u$ q: y4 E. t
5 h# d; V: ? W7 G, T) W" t/ W8 n
1 m$ ^. b$ i' H) ]. X% o+ T, k
// Dummy Implementation to be used when no other implementation is available
4 y6 ^% S/ r0 ]+ Hclass CUPnPImplNone: public CUPnPImpl" P5 c7 ]* G- V+ D( |1 N
{
6 h. X& K. _5 }8 o( e Rpublic:
& k/ _' x7 K0 `8 o: \" `! t H virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }' u% V! I$ p! D+ F2 v2 ]
virtual bool CheckAndRefresh() { return false; }
) M# E8 d- c# E9 R7 y virtual void StopAsyncFind() { }6 |# i3 H* T: N1 T7 e
virtual void DeletePorts() { }
! q! B; c6 S% v7 ~/ g4 R virtual bool IsReady() { return false; }7 _# E% N1 _4 Q
virtual int GetImplementationID() { return UPNP_IMPL_NONE; }+ F) w' v# d# @' ?1 H
};' I% c- f$ [3 Z& {' f# D. R) x$ n' F
3 ?( c x. b* ] Z$ D0 x' A
* D) \7 ]8 A7 U
/////////////////////////////////////4 m7 S6 Q3 @- u
//下面是使用windows操作系统自带的UPNP功能的子类4 p9 S$ Y& Y) @ U- b
0 q8 n( {, |0 u; W% x$ F6 O) {! s
* S6 q8 l _' W/ F! c8 W6 Y+ m#pragma once0 T0 r" }6 q4 k& @. p$ \# `( A
#pragma warning( disable: 4355 )# M& I- Y# u9 o' }
+ \) {, i) t, v* \& o) k; @5 M
5 g. Y- q# R! m: c% w
#include "UPnPImpl.h"
% [ k2 u# s- G7 K3 n# S# h4 X/ y5 s#include <upnp.h>
0 z' V& `1 G+ F3 ~#include <iphlpapi.h>
; m9 g: t3 g1 Z2 j- d6 Z#include <comdef.h>' Y- `: A, U: g3 H" Q$ g
#include <winsvc.h>" m, G4 _/ J; H7 E/ k
$ ]" ?+ \3 Q# q3 J$ F: s$ C8 H
; [! {7 A3 E$ ~! i) [
#include <vector>" M' R7 f& Q4 v. \3 G, m
#include <exception>
4 V2 T7 \5 T% v#include <functional>( G7 o. q/ Q% C) Z' ]
+ Z- @# H: \) s* H" ^" `
6 ~0 f( L& z* n
9 n9 ~' g" a/ `5 Z u, {5 g) j. }8 P% g/ h, b% O1 l6 Z+ T
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;6 q, N. i; O: X0 j8 K
typedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;8 G* A6 L' t# ^) c- ]9 I# Q
typedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;
3 r; }" X$ p( |typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;: {6 h# I2 i* @- ^( J7 z
typedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;3 ]. y) ^9 W9 C) R+ h0 B/ S8 L, h
typedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;: W) ^3 u& s: P8 m/ _
typedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;
# F" x1 G. K. E" G2 i, n. g: Q, _9 R# {0 i5 \ U
( e8 }) ~- B8 B- d
typedef DWORD (WINAPI* TGetBestInterface) (
/ ^ g9 `3 @3 r3 V7 R IPAddr dwDestAddr,
0 y4 j' x/ N& {* e: Y L+ } PDWORD pdwBestIfIndex
; |" W4 y9 ^; J7 v8 c3 d6 [ d);
% N0 P$ N8 s* O6 `+ K0 a
$ d, A0 e% s4 _9 C G( ^
! @: f! _3 {5 ~- ?, V0 ttypedef DWORD (WINAPI* TGetIpAddrTable) (
+ U, Q/ @# Y& ]) L$ c, a. n3 W' G% i PMIB_IPADDRTABLE pIpAddrTable,( r3 g- a5 W- u0 |8 ?1 A- R
PULONG pdwSize,
6 i A$ d0 ?& G _7 y BOOL bOrder
& H5 v a2 g" n. k);5 X3 v, R2 ^6 O9 c; I
# O4 ]& v' v7 m$ z
& t1 c3 r3 o. S9 [. ~" [5 z
typedef DWORD (WINAPI* TGetIfEntry) (1 B2 @8 X& E: M" j! W
PMIB_IFROW pIfRow
* |" f# K+ U8 R);
0 R( o0 x% F5 `+ h4 }
2 o/ Z9 v0 J) d; a# h% |" P9 Z R8 Y6 j. X$ _; c
CString translateUPnPResult(HRESULT hr);
6 V) L$ \8 W. r' h0 ZHRESULT UPnPMessage(HRESULT hr);4 B* c' T/ W8 |' \- H% k
& s. p0 e" k; ]/ F* \/ g
9 V9 E8 E9 g% ], f' M6 Iclass CUPnPImplWinServ: public CUPnPImpl
+ l. m# G6 x4 w" J9 [6 ?{
2 x/ C0 P1 x, d friend class CDeviceFinderCallback;
* B) F& }( H6 V friend class CServiceCallback;/ V- [) [7 C9 D
// Construction
6 ~8 o9 g! |0 w( \0 _1 K- Ppublic:
R2 T# f; I- l: t/ ~6 T virtual ~CUPnPImplWinServ();
- X1 r& s: Q0 l8 U- g z CUPnPImplWinServ();
$ \ }. N5 ?) T" `$ t* l, I) i8 b# Q3 {! D( U
2 f% X& n# W& r- g/ C virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }
" x- X* w# U. f3 L8 e0 R' c! H' x/ o virtual void StopAsyncFind();8 p0 P5 V: U( G8 q4 {. ]
virtual void DeletePorts();& |% S! A" O( i5 c
virtual bool IsReady();% N% ~: }7 g, g5 L: Y5 c% w T
virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }
6 H( j$ B! P6 h4 T {$ e, @+ a& r" C+ H% o
9 U7 U$ o+ a. b" A e( J$ m
// No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)
: q$ m) I' d' S! p0 B9 y6 v2 D // the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later
! X0 H. H. D' ?* ]1 k" w virtual bool CheckAndRefresh() { return false; };
9 i: y1 }; v2 j* \
" v' c3 T0 t D8 x7 }' E ]2 F& s; e8 h
protected:
; X7 k+ z) T& N1 M void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);7 k. z7 F. [' U# U" p
void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);2 o1 K, G+ }4 ^7 E
void RemoveDevice(CComBSTR bsUDN); d, _* P6 b6 v% C# ]
bool OnSearchComplete();9 v0 S7 S+ a# g! Q7 N
void Init();& U, z- V6 j" P, U! U3 h1 F
# Y% V8 H# d2 L6 [/ [5 `
' Y1 }/ |% z& x
inline bool IsAsyncFindRunning() 2 }" _9 g3 z* I% |3 C2 s
{2 m+ w% ]* G7 C; t: M% {2 ?
if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )5 b* H' d. E, d9 C r
{
?+ N0 Q: x# T8 n- a7 P m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );
- M6 b# z: F& k1 @) X( L Y m_bAsyncFindRunning = false;
8 U0 q7 ]) G2 Z B( y' ~: j }4 M h' I# G2 n' U! g8 [
MSG msg;0 F. O& [6 w, ?2 p. `9 d5 i( _
while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )% [( r+ p& a; S2 p
{8 K& {- v1 I; \) q
TranslateMessage( &msg );
$ y3 f$ I! m: D* D; L) p DispatchMessage( &msg );
4 P2 y4 ~' q1 C# s- \- q* L }
4 P& L& `3 d( p3 f8 `: A. E return m_bAsyncFindRunning; P6 j Z5 r3 Y }/ B7 Z
}
3 D% W5 h' D( g: L
& u( q7 K3 V* i$ F
' y' j L3 P3 x3 Y- [7 P TRISTATE m_bUPnPDeviceConnected;
( J z3 A- i) _! u% X6 |3 K% X: T2 F2 ?
. @# `% F3 ]3 |0 `% H' {1 s! w// Implementation7 j2 s. b6 ^4 p
// API functions% Z) ~& O+ Y3 e+ o
SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);
/ _3 Q8 u7 k: G6 [0 x/ U; A, i; C SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);
. o! J( }7 j: U: S" B4 U1 ]9 i BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);$ R& g7 A" g- I8 o3 ^1 S
BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE); M; Y7 W; b, T, p8 Y
BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);. V' H0 |/ Y+ k- ?4 g8 {
BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);
0 n6 {* q4 z7 E! J1 A' z6 o3 t/ Z& L: Y. d) W7 q3 j }+ v1 U" f$ A
* {$ D7 W' Q3 K" b; y) V TGetBestInterface m_pfGetBestInterface;
/ U( C8 I+ @: S) T TGetIpAddrTable m_pfGetIpAddrTable;
& |( F+ \6 l( \7 _1 } TGetIfEntry m_pfGetIfEntry;% Q- n5 v/ l$ F6 I
! ~- a. \6 h0 g
$ x( X8 H# V6 M- p5 Z9 n
static FinderPointer CreateFinderInstance();
& l9 G& j& t+ l+ p4 w# q! O2 i struct FindDevice : std::unary_function< DevicePointer, bool >
; \( r# i. {! i* k% ?, m {5 N! ]4 y) p. R% I- g1 q
FindDevice(const CComBSTR& udn) : m_udn( udn ) {}
% T3 G& f) u. ]9 o2 q% h result_type operator()(argument_type device) const
6 I N7 m8 N/ B3 {7 [) S0 e {
# V2 z' H4 g4 Q/ Q. Z CComBSTR deviceName;
9 ^9 U+ ]3 K8 z" L o; k HRESULT hr = device->get_UniqueDeviceName( &deviceName );1 I- M9 v0 a' {, [# k0 {: |$ n! K
7 I M: {9 m: o9 H+ F$ t3 c, N; ~: |
if ( FAILED( hr ) )
9 M! S1 t+ k, g% @. d3 Y" C" Y2 `. E return UPnPMessage( hr ), false;
* W" F+ I+ Y. j3 `3 c9 ^+ v
1 r7 v8 L7 L8 I5 l. n# K
0 B a7 A4 d% O- _2 T return wcscmp( deviceName.m_str, m_udn ) == 0;
! ~7 Z6 T8 H$ J9 E1 V# S }# h* N4 S& R$ o; O# t
CComBSTR m_udn;# x9 I4 d* _6 E) D' h0 v
};% S3 a/ u( ?# w: d2 C' p
6 C. E& f- z+ s) Y void ProcessAsyncFind(CComBSTR bsSearchType);8 _; L5 k6 M! u2 A) i
HRESULT GetDeviceServices(DevicePointer pDevice);
6 A5 V1 }- R2 ]; g: | void StartPortMapping();/ E1 T- U+ j; C. i9 _
HRESULT MapPort(const ServicePointer& service);
- l' s6 P/ u& Y& j { void DeleteExistingPortMappings(ServicePointer pService); Y. _1 x! r7 a" \
void CreatePortMappings(ServicePointer pService);
% r% K. @) p* J HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);
; B( q1 }5 M0 _! R# S HRESULT InvokeAction(ServicePointer pService, CComBSTR action,
, I% O, w0 @% Z0 s! [ LPCTSTR pszInArgString, CString& strResult);
3 A4 C% j; j4 @0 l void StopUPnPService();
9 \) G, t# `9 F4 y+ {) a
' U, d; L; b* r* i, E/ o" k. p, f( T& [( Z
// Utility functions
2 b* X5 N( B K! L) j+ P2 N' ` HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);
% u0 e! A0 @5 M' t# y INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);
9 i ~) m, U# Q% p; K INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);
( J0 W5 X9 i! g# C/ H1 V void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);+ j# g. u* ?, h6 ]) g- I. t: u# A
HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);
4 H1 U5 ~9 R+ l. S- ^ HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);! `" T9 ] R1 H) O) Z
CString GetLocalRoutableIP(ServicePointer pService);
3 Y, z9 H3 l3 n4 W' K! T7 m. ~/ k2 p0 V9 w3 ?2 J( v. E' F$ \
4 i* w& g, E2 a// Private members
! [. M) z( K- w( g( k( J. Zprivate:
8 l9 ^6 _* U9 b/ e7 H; u6 S DWORD m_tLastEvent; // When the last event was received?! N% k1 Y3 Q' {2 u) q8 _
std::vector< DevicePointer > m_pDevices;
) _ e- p$ F( L. o7 a std::vector< ServicePointer > m_pServices;
3 ~/ ?+ x8 p) B FinderPointer m_pDeviceFinder;* ~! G' m- Y8 u# c* j
DeviceFinderCallback m_pDeviceFinderCallback;3 f( z1 e( D* {( |& V
ServiceCallback m_pServiceCallback;
0 }- d! s; j6 B& b& K% R a% G1 G0 W- x- @9 G* P
' E4 [8 @( P9 M6 V. U- o# e LONG m_nAsyncFindHandle;
- {& X3 B" V J- z) L4 ]3 T bool m_bCOM;
, h) `7 x5 v! K7 j9 L% Q bool m_bPortIsFree; M+ e" @+ |; ^, f
CString m_sLocalIP;) C b, w6 {: V) }! ?( f' N: b
CString m_sExternalIP;
( S% Z, w! z! u/ V4 U8 F1 | bool m_bADSL; // Is the device ADSL?
' v* S0 H B/ X bool m_ADSLFailed; // Did port mapping failed for the ADSL device?* }/ L( r6 h! P! U) s4 i
bool m_bInited;7 Q' @" {0 d1 @9 c2 t/ M8 m6 u n
bool m_bAsyncFindRunning;0 d1 n9 n8 {' f" x q$ W) t* k
HMODULE m_hADVAPI32_DLL;
+ s( n! b' X) _0 S6 T* E HMODULE m_hIPHLPAPI_DLL;$ L- N3 `% p6 ^- F" h# c9 R
bool m_bSecondTry;5 U _, W' U& X( Z; U
bool m_bServiceStartedByEmule;
6 u' b$ t$ p, R, j$ g4 v bool m_bDisableWANIPSetup;
& ~' _; }: W, L& G, E: i bool m_bDisableWANPPPSetup;
& ~& k2 w$ l8 d3 x) v* r# }4 {& A& m/ L; R
) U m/ ~( C3 B3 H r9 G
};9 q* N. @2 C3 B" h# Z n" v
# r2 _/ g1 B# ?% S
3 _; b% v2 {9 r/ _: P// DeviceFinder Callback
5 g. o% G1 ?; _( Q4 n9 q8 \0 Oclass CDeviceFinderCallback6 a, e$ C+ ~$ ~' Y% z6 Z) n
: public IUPnPDeviceFinderCallback6 @/ @1 z% U7 H3 _! N1 L' t, N1 i
{& i" V) E+ l5 W# T5 T' L0 c; F
public:) d- D( z* }% y5 S
CDeviceFinderCallback(CUPnPImplWinServ& instance)
! y- R3 u# b6 h : m_instance( instance )
8 z8 Z; [- @* [# W1 J: D% h { m_lRefCount = 0; }/ K/ F" D( j; f5 x! h" Y
! n0 y+ l8 d7 ]) v: m, Y
2 N( l3 _5 J9 R) l- I& d STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
$ M, s& J& x% r$ @2 J STDMETHODIMP_(ULONG) AddRef();
' g& Y2 Z$ ]" l- \ STDMETHODIMP_(ULONG) Release();
" B: W: B: G! M) Q. r( I
1 I6 ^. m3 _3 P9 M8 c h" S
$ o* \) ?, q- }6 {) M; ^& f- l$ B// implementation
0 W) l( ~( v! E+ w* ~( E# Kprivate:
7 z! S% W' M$ v HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);7 L- k; X: ~0 n, ?
HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);
' E( L$ U, U. \$ O0 t HRESULT __stdcall SearchComplete(LONG nFindData);
) d. j5 D) @: e. ]& [0 N; T0 z) r* s; |$ C! V$ p% u
* B% S& {) C% C* s
private:3 I6 S) g- B+ ~3 a
CUPnPImplWinServ& m_instance;
6 F; G- d8 u0 r+ { LONG m_lRefCount;; a+ A& @! r5 `
};3 U! O& W1 ~/ y
+ Q& ^$ ^* a: Q# Z
& R* g9 M' m, Q# v1 M// Service Callback 8 d# R; V, Y+ N% q2 S) o% H+ ]1 O
class CServiceCallback2 S, k2 e% Y* v; r3 Z. z% N
: public IUPnPServiceCallback# V0 U' q9 v+ b3 H# ~$ ^
{/ k7 t- u( y* U6 q7 ?
public:
; P! k; f* E% k3 G& b0 j* z6 k- j7 W CServiceCallback(CUPnPImplWinServ& instance)1 b* G+ k; l1 \4 I
: m_instance( instance )! g# R. h) `/ `; Q4 C0 E3 S
{ m_lRefCount = 0; }
9 b B0 E1 ?, f2 Y! J. I - X) X4 s; I: H5 s$ n5 l8 ~' O
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);5 Y& m' y* D& b
STDMETHODIMP_(ULONG) AddRef();; T/ P+ x6 @: H
STDMETHODIMP_(ULONG) Release();. T! g+ d2 f2 \. O/ K
; T) N) ~. ]7 t$ ~' x
. c- Z( K# [2 V, Q9 s; S1 a1 Q// implementation
. c0 j! W" P* P: N5 ~; B1 b5 lprivate:8 o0 S1 Q1 F& |0 t2 y& g$ f
HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);; @" w% ~% g# e6 b! M- O; D
HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);
7 y/ R) v( p6 o) O8 [* @
/ Y1 R1 y J6 p* C" |: q: W. h5 q( O7 H- K: i0 B" i* l
private:
f# h& L9 H' X CUPnPImplWinServ& m_instance;' |4 N G1 P$ E! [- U# d
LONG m_lRefCount;
0 t5 R N. j! z: m};
7 l7 E- j0 K+ O6 h! X% }4 T6 x5 E* T2 T6 l. _
; H( e' E3 x D0 v
/////////////////////////////////////////////////
" I/ @* V" C3 l6 G1 Z) O2 Q# K% C: A! G/ t
, _" ]0 G8 H0 N# O
使用时只需要使用抽象类的接口。1 C' |2 k @0 W4 ^+ I: L/ h; p+ v
CUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.) }1 d* n( J. n: ]
CUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.
) N% m$ a( E; C3 w2 KCUPnPImpl::StopAsyncFind停止设备查找.
3 T% s' F' ], l1 B, aCUPnPImpl::DeletePorts删除端口映射. |
|