|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule,* T" E% p) ]5 A8 Q
% d" T3 E0 _. O( u2 j1 v6 G) ?- h9 G* U* Y; P
///////////////////////////////////////////4 ^. A9 q% u, {) s" F5 h
//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.) ~/ _& s" L$ u
/ L2 f& s- r% j' I& q
- G* |! ^5 U6 P
#pragma once
. [: Q& T2 P) g#include <exception>/ m: i, Z" ^7 d
9 X- G. E( \7 Y1 w5 w+ A
; j+ Y6 q- G3 N: o# f enum TRISTATE{
) l x5 \- e) A0 V- \) o TRIS_FALSE, T% t' ~ f% }8 W
TRIS_UNKNOWN,$ W1 S: c: |; b/ \: h8 s% o9 n
TRIS_TRUE
& l$ \7 W3 B, A};
1 a5 k; M) y0 b! @0 `+ ~3 \5 V5 g1 X4 P0 o7 Z
! J& t; e, D0 N2 ?1 j2 E, g
enum UPNP_IMPLEMENTATION{& W3 Z- q7 G5 y2 d* r7 z
UPNP_IMPL_WINDOWSERVICE = 0,9 }0 H( e. N4 ?3 I5 l, |; X8 q
UPNP_IMPL_MINIUPNPLIB,+ u! p! d3 l* z2 ?% F8 f4 k' A/ b' q
UPNP_IMPL_NONE /*last*/
3 k' u. l E" | E};
2 F& K) S" X2 U7 l- ^
& U$ i$ V1 O3 `4 p. b0 t
/ x8 S" M% H" S/ S6 ~) h5 T5 J, K% z
: t8 B$ _; D( {2 V0 B8 p7 `$ m; E( K7 _" r
class CUPnPImpl3 Y. E6 o8 H0 }/ f- k) |
{
$ J( ?+ X8 V# @" p& Opublic:
4 B0 _: @0 y! N& E CUPnPImpl();
7 C3 J& g7 O2 o C0 S virtual ~CUPnPImpl();
. q+ H1 V e5 N1 x2 N struct UPnPError : std::exception {};
) d* I# U {/ C$ j enum {
9 q, c! p' R7 G UPNP_OK,! a( t% m- c0 v$ {, f: q
UPNP_FAILED,
$ h$ z" T2 _( p I7 H7 F* j% e9 e UPNP_TIMEOUT- \3 O3 Y3 }7 p
};
. V8 ]& ]4 d/ H" k. q% S
7 B- n& L/ ^0 ]3 C) U, v: ]% R' s5 G: d: d
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;
% L6 V0 d9 W/ g7 W% V6 \4 t virtual bool CheckAndRefresh() = 0;. a! z. b; I' e: |
virtual void StopAsyncFind() = 0;: l6 f; N8 i0 ?
virtual void DeletePorts() = 0;0 x% h$ A+ S' h
virtual bool IsReady() = 0;7 L2 W/ r7 p, {1 k
virtual int GetImplementationID() = 0; m, v) O# d5 h: q( H8 o1 W' j4 e" o
4 \; l, X) K, q6 d void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping
" T# W8 F" r+ r4 ]0 O+ l/ |9 c: H
b/ [* L4 A& t2 m) I2 G U
4 X' r& `/ o7 {3 n; d' ?$ ?% W void SetMessageOnResult(HWND hWindow, UINT nMessageID);
( y2 T- q0 Q0 H% P# Y Y0 p TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }
" x+ X: X' G8 y6 g. y5 g, J uint16 GetUsedTCPPort() { return m_nTCPPort; }% f7 [. ^) n; X, p% \& q9 W
uint16 GetUsedUDPPort() { return m_nUDPPort; } ; t, e, e* [3 W: k. l! w/ Z6 M
/ y* y+ j' Z" {/ @
7 o& O; i1 z4 i
// Implementation
' B! ?6 l: @; x! _- Nprotected:
+ i5 A0 N- l1 b$ J volatile TRISTATE m_bUPnPPortsForwarded;3 q" G) M1 `! H0 D0 b. p$ p
void SendResultMessage();$ r* C, g) d' X6 H) X2 ?$ G
uint16 m_nUDPPort;& z U" o$ [$ J$ X$ q
uint16 m_nTCPPort;2 O) F+ \* A; Y9 i$ h4 k
uint16 m_nTCPWebPort;
4 P. d8 v+ R# c0 f9 G3 s5 D bool m_bCheckAndRefresh;% E& O' @1 [ j. M" b( P
. G: j% R6 _* [) N- m% ?
, D0 J$ a/ s" yprivate:
5 X3 a1 F6 R/ l; r6 |( E2 I HWND m_hResultMessageWindow;9 k) z+ l5 @( o+ F- |5 D
UINT m_nResultMessageID;! n1 {* R. D) @9 G
% x% m: j' m+ B4 G5 Z1 m
! y2 V. T) ]; B% Q! x
};% J" o+ _6 ]" K( n+ f/ w) {0 g
o v5 e8 Y3 T
) O5 M7 { V; @3 |% [) o: X. t
// Dummy Implementation to be used when no other implementation is available
( ^, `4 t9 {, vclass CUPnPImplNone: public CUPnPImpl
( S1 t$ O4 [8 K4 E{
. T4 T9 B, M' `- l2 D) I$ Wpublic:1 d5 P! k( h+ m
virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }/ b* Z$ c+ I9 N' J6 F
virtual bool CheckAndRefresh() { return false; }" a% i, ]7 o5 n
virtual void StopAsyncFind() { }
& f3 j+ b& b% w$ ~+ G' B virtual void DeletePorts() { }
- o: _8 ~( r) }& I virtual bool IsReady() { return false; }
& i$ w8 S" P, k& q/ R3 @, v! W5 Z virtual int GetImplementationID() { return UPNP_IMPL_NONE; }
' i) F- J# X# ?) s/ }};
; g* g' Z# ^) T% W' ^( S9 ?2 D" \$ U! l
! o7 x6 U0 {: B* i j- {0 W4 H! {
/////////////////////////////////////( ?+ x( m6 l# l2 b& X+ L. }
//下面是使用windows操作系统自带的UPNP功能的子类
% B5 D8 f* g/ }
2 D" M' ?9 E/ v9 R( X# P4 E1 Q! b% r" K4 D" B$ A
#pragma once+ \5 m, N+ B. T2 K
#pragma warning( disable: 4355 )
7 z' T4 \$ Q: O; L* b+ q/ C
. M) M; J* `' x, N5 R) `- r. ^" j1 [; V8 ?0 d1 ?
#include "UPnPImpl.h"4 x" F! }7 |: H( s' m9 e" q& o
#include <upnp.h>* d: X' z" O+ D: U/ z
#include <iphlpapi.h>
, I+ w% ]/ p, V: @#include <comdef.h>
/ E/ D+ O# A S3 J7 c#include <winsvc.h>( U I. \/ g3 q+ D6 G$ H' `
7 ^7 U) ^. h' P& \# F9 \$ F/ S y: H8 \# e
#include <vector># H, W6 A! D+ @6 G0 {% S
#include <exception>
- M3 b3 a6 a* s1 j- e! j#include <functional>3 b7 y! `2 m. b4 b7 ?& [
6 Y. \, b, i. Z* q9 z; F0 c* t
3 K2 P6 i: D0 r( E W
7 d5 h9 [$ R! k; x
' t& M& j4 @' x: S) s& g
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;% v4 Z, V% U0 Q
typedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;0 U/ E4 ^/ u, }5 y2 O2 z5 s+ f( z- A
typedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;' \/ s% z5 P% ]2 ]- r5 p
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;4 a1 c8 j6 G" z( }; B s7 a
typedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;
3 t7 R% k# Z1 N E! ^0 gtypedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;2 P5 p9 [. J8 H
typedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;
; g+ u1 `; j6 f0 Q2 p: k" H& E9 q/ E2 X3 i* d! w
H6 r O5 }& s, Ctypedef DWORD (WINAPI* TGetBestInterface) (
) x" ^7 C( ]# M2 @# d5 m IPAddr dwDestAddr,
# j! [9 h+ i1 s6 S/ z1 Y) A PDWORD pdwBestIfIndex
. G. Z# _( K$ F: s$ {+ t; F);
. x1 p9 L) Z, @0 H! c) v
# v9 U7 {0 @2 s) k+ C5 C& V; |* o8 c- Z+ s
typedef DWORD (WINAPI* TGetIpAddrTable) (
# A& b+ N% l* M PMIB_IPADDRTABLE pIpAddrTable,; c/ ]: D2 Z: w* w& Z' e
PULONG pdwSize,
# }5 h7 I4 ?7 N) Q# c% r4 u& n BOOL bOrder" A t( Y" e4 V: X& j
);$ c3 Y. d2 v8 E- ]/ o' `9 S
3 T& I" U/ r) p, A+ g. [
. W% O2 p0 F+ C9 t# I
typedef DWORD (WINAPI* TGetIfEntry) (# g+ B% l0 g" i5 L! ]6 d
PMIB_IFROW pIfRow* i' ^6 @2 y% ]" l
);
( N. N/ q2 l6 u0 S
" z$ s2 m r9 H5 G* t, _9 {" S# h c* I1 T4 X& D& u
CString translateUPnPResult(HRESULT hr);: ]' L" Q# v: \
HRESULT UPnPMessage(HRESULT hr);( o- N& ^6 v6 X( _' Z: r! |, c' U
1 P* r) J W7 P1 g" l3 d' h
. M h% p+ z; E1 c( H
class CUPnPImplWinServ: public CUPnPImpl7 R6 ]0 x% p7 B4 P( R: {: D4 K" m y
{
) G6 J. S5 Y% k3 Z$ F+ y+ X; N+ ] friend class CDeviceFinderCallback;
1 f1 Y% }" E, a* E- G friend class CServiceCallback;( q8 s! `5 [* F
// Construction
- j8 G5 n4 V& a9 Qpublic:4 S/ Z' M1 c& J" ^3 A
virtual ~CUPnPImplWinServ();! B; h2 ~; O" L' Y4 O& B7 Y9 q
CUPnPImplWinServ();
4 \* i ]9 l" N. D8 w( i
* k6 E; c: b1 I; q) T- V( C; Z5 U+ c
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }# K9 p ~; E2 v8 t0 I) {
virtual void StopAsyncFind();
s+ Q7 Y, t6 k- D virtual void DeletePorts();
& b9 [2 @5 q: E2 C virtual bool IsReady(); z% D( @6 a+ u9 U2 a. I) v+ L
virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }
6 e; C. K1 X/ N) n" I3 ~) A; {6 V" n3 p. D7 ~2 z
8 L" |- ?- B" X2 F! F2 t0 Y% A- V: X
// No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)5 C( j5 T, t3 `" e. J
// the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later
9 X& g A* B P, U virtual bool CheckAndRefresh() { return false; };
& v7 e3 }8 K/ A9 J; y
# |! z' I0 b0 i2 V- w. F/ @3 t! O
; N) z5 }& Z4 h0 R2 G. ?protected:) U* M" D, F0 c& H0 ?' k/ ?5 ^" E0 L- l4 M
void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);
( t" Q Q, h% x0 V/ { void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);, w8 X! b; v, ?1 K
void RemoveDevice(CComBSTR bsUDN);
d" Q: E* _7 I0 m bool OnSearchComplete();& _4 v" N4 e3 k; f% L8 e V
void Init();2 m5 W7 {* N5 z+ w9 f. R
# D2 k( x- i/ C! ^' |, N: a
" e$ C- X; ?, R9 O2 i6 p5 A inline bool IsAsyncFindRunning()
8 u8 x* `$ f% A9 t, s7 m/ b {2 Z5 p/ K- J! R5 m5 e7 L
if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )8 c0 |4 g4 ?* ^! G
{5 h# {0 R! H" b
m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );
3 d# X+ A( k4 p m_bAsyncFindRunning = false;9 h. t/ e6 ~5 f6 V( F3 E
}
" G" k! Y' w0 G R" v MSG msg;
. W P; `+ O" P! k6 N while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
2 u6 } R" b7 S+ Q- j) s {
L% R+ C$ D3 Y6 L' O6 u TranslateMessage( &msg );
4 x# H( L5 I, M- B8 [! a- H DispatchMessage( &msg );
8 u) ?' t* x' t }
5 C/ U! k( ?# p8 m return m_bAsyncFindRunning;
5 r X* N# l' e+ u! a5 E8 f: b. v } ^, X+ R' \. M2 J9 Z
- O9 H7 B/ f# x% @1 a
^; _ O3 _% I' B: ~5 ^
TRISTATE m_bUPnPDeviceConnected;
; g0 k8 q3 X& N Z. R
0 c. q0 t$ ]: [5 _8 m9 y
; u/ c' q# c) ]6 d9 _// Implementation: f% o# ~+ e% B& n4 f. \
// API functions7 L9 o! y+ [6 N
SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);7 f5 X. U; j4 a# ]
SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);6 J. H) [( i: u, P* o! p
BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);! w7 S7 m7 a; ?
BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);
# p; G# U1 Z; |5 [2 ? BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);. N7 S& {7 _1 W
BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);
0 O- q, c/ d" ]9 z( p0 r0 m4 L! N8 N# d/ h0 I- D
9 w2 h' V6 _# \+ a! I TGetBestInterface m_pfGetBestInterface;
2 r: s" g# X) @8 u+ \4 Y: P TGetIpAddrTable m_pfGetIpAddrTable;
% f) g& P; V! Q TGetIfEntry m_pfGetIfEntry;
: D/ ?6 v) c, k6 a; z/ ~0 a" U
' q9 a$ W1 W6 J1 I1 e' P6 O0 K! w5 L& O
static FinderPointer CreateFinderInstance();- A! v4 O) U% A9 I# y
struct FindDevice : std::unary_function< DevicePointer, bool >7 I$ V6 \, n9 e, ?. S0 {+ l+ X. l
{8 F6 ~7 ]3 h, K& a X
FindDevice(const CComBSTR& udn) : m_udn( udn ) {}
) }3 g# ?- p x# R% [7 V result_type operator()(argument_type device) const" K+ o8 Z1 l; r$ M5 H+ Q/ i
{7 R% V: l. x( t* c: N; E, [
CComBSTR deviceName;
' C1 Q. y& q5 d* A* m3 M4 u HRESULT hr = device->get_UniqueDeviceName( &deviceName );1 [1 r3 h0 _* u. \9 h* T$ S( O& h
4 o+ \$ c# C6 E' o
) K# _1 ]3 S b: k, V, A+ Q
if ( FAILED( hr ) )
3 b* w9 O& c! G) G: R return UPnPMessage( hr ), false;
2 ?0 c5 b* C; Q/ \' k% i8 E
- z- |% R1 \1 d( Z s( I' z5 J; j$ ?- M& M8 A9 l6 l% U
return wcscmp( deviceName.m_str, m_udn ) == 0;) s2 o0 w- H: j; ?2 D8 o' X
}+ g4 S4 f& j: s/ |- ?
CComBSTR m_udn;. v. F' U4 ^, Q6 L0 H
};1 m& H! \/ r% e: t* J5 }
' S) |0 S# [) Y' W4 w( w
void ProcessAsyncFind(CComBSTR bsSearchType);6 T2 w1 C& L& C2 B0 t* @
HRESULT GetDeviceServices(DevicePointer pDevice);" i$ |- _% G& A$ V( Y
void StartPortMapping();
+ S) N' b/ `* q6 i. O HRESULT MapPort(const ServicePointer& service);
4 [0 Y+ g) D6 f3 G) R void DeleteExistingPortMappings(ServicePointer pService);3 ^" A+ D- p" n% ?8 z& ~1 J8 }) k
void CreatePortMappings(ServicePointer pService);
* a% Z% ?1 I* S, `& E9 | HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);
) ^4 v1 ?" b+ W. v% X HRESULT InvokeAction(ServicePointer pService, CComBSTR action,
, c. S- Q; V" |2 m5 l. h LPCTSTR pszInArgString, CString& strResult);
4 J6 V) v; x( B' U# f* g4 V void StopUPnPService();$ r$ _$ ~7 A/ [0 o* ~; a+ ]
3 B2 E/ z' ~8 P6 u/ M6 @6 }, k: y
: d' e+ a6 f+ K$ X" R7 J$ B9 Y // Utility functions7 L4 U& f: y* A$ i( G+ b/ T
HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);
8 E. s% l- U8 z* Q; @( k* E0 Y6 \, _ INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);$ a% ]: }1 p% X- q6 c# g) t7 }) h
INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);/ R$ w' }& L J. V5 U9 h
void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);
1 Z: {8 H- `' D HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);2 e0 _4 k# f( [
HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);+ _* M j/ C- k3 ~2 r' o+ x: y0 C
CString GetLocalRoutableIP(ServicePointer pService);. A& Q W- F' M% Q, w# ~1 ~0 `! n' L- P
! x2 T! S) |; m% J5 N. F
$ c t/ \6 ?5 G* e5 T' y! }6 t// Private members* j+ O0 ^! C2 W/ g% \+ j1 b
private:/ O: g; ]+ l% z: d6 g5 I8 K
DWORD m_tLastEvent; // When the last event was received?9 X# Z9 e! a5 ?; ^- c* \6 m: s
std::vector< DevicePointer > m_pDevices;0 ]! }1 ?2 h& R- r
std::vector< ServicePointer > m_pServices;
+ H2 c; H- j9 U- v FinderPointer m_pDeviceFinder;
& V- S" T. y4 J7 e, X* Z DeviceFinderCallback m_pDeviceFinderCallback;
" {8 y3 N% X+ j# Z/ e9 v& N ServiceCallback m_pServiceCallback;
W& C" @: U$ y) X, b) K8 }9 J9 p4 z! ^# t' ?0 B9 _5 ?- c
+ V- ?* L% e- M, N: L& g5 G% V$ A: O
LONG m_nAsyncFindHandle;( G) ^# L3 _* O8 b- m
bool m_bCOM;
( ?' i3 t* Q8 ^# z2 V; O) g2 p$ W5 \ bool m_bPortIsFree;% o: ?$ {- J& g; D( a
CString m_sLocalIP;! v+ B/ b3 ` m' |
CString m_sExternalIP;2 k! P" a8 l Q
bool m_bADSL; // Is the device ADSL?* [6 v4 E2 e- h3 U+ N" ~8 R$ D
bool m_ADSLFailed; // Did port mapping failed for the ADSL device?9 B( l( B% g$ I$ n: \6 v4 I
bool m_bInited;
5 c0 c4 q7 |/ x6 P7 t5 E bool m_bAsyncFindRunning;+ _- m8 [2 r+ r' m
HMODULE m_hADVAPI32_DLL;: j' s; b) Q c: R$ d
HMODULE m_hIPHLPAPI_DLL;) g3 C% ]7 k& }: l I/ {
bool m_bSecondTry;
/ U3 H5 b; i2 U% ?) V: H* ~ bool m_bServiceStartedByEmule;3 V) j, @3 {$ P4 j; Y8 \3 N2 \' ^
bool m_bDisableWANIPSetup;/ w" F! m& Q* r2 X
bool m_bDisableWANPPPSetup;* i# K0 y* z% F& X' a3 j3 x5 u
0 q4 \7 N9 p. p4 t k; I( j r' o w' l
};6 ~! L7 K' _0 _
. e; `0 \; j+ o, p* O+ b1 b7 f9 s3 Q
: U% J( m) u0 O% L
// DeviceFinder Callback
* l7 j# P/ L0 U4 e- V. [+ \0 eclass CDeviceFinderCallback- Z' E) l- ~- ]$ ^7 n2 x
: public IUPnPDeviceFinderCallback
, _" b* @; z: T: |. |2 x3 J* `{
7 H) ?# H6 y4 g/ k* u5 Opublic:- U4 f! F, {, H
CDeviceFinderCallback(CUPnPImplWinServ& instance)2 c3 A: j# ?, X! A" s3 E& w8 n& ]
: m_instance( instance )$ Q7 L: E/ M& d4 f0 T# F9 h
{ m_lRefCount = 0; }; [2 B" f6 m. ?3 q# x: g3 N
3 |, @ l1 ?; e+ e( q+ b3 {, E( o* j# N& @+ j, p0 R8 P7 `
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);9 g d5 L1 _$ }0 N8 l7 w
STDMETHODIMP_(ULONG) AddRef();. a1 q1 B6 l' K: P: x
STDMETHODIMP_(ULONG) Release();
- A: C5 c; o: a' A) f; ^" q: s6 ^/ Q9 \8 n9 A7 a% J4 L
$ ~& S4 \, C+ s. x// implementation
$ f7 ^( ]7 u4 Kprivate:
/ \) K: I- F9 n! x+ p HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);
' F2 ~) U1 G! b) w# R7 A$ C# K HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);- ]4 ^% V4 R1 I# {- h! q7 \
HRESULT __stdcall SearchComplete(LONG nFindData);: s% E# m2 q6 ^; R ]; @ S7 I
. E- Y5 E1 m4 b4 Z/ J! t7 K2 ?+ a- ]+ o2 c
private:0 H1 f/ s8 U8 T1 O
CUPnPImplWinServ& m_instance;
3 g) b. W5 k/ x* n. ^ LONG m_lRefCount;: Q1 D% x" f0 U+ b/ H
};/ [0 _( K( O' g
" K7 g! V: [; S1 y+ ?" S( b& f }) B5 }0 d% L% ]
// Service Callback j: b- r: C6 K
class CServiceCallback9 E! g! h9 D- Z9 e7 B" z# j
: public IUPnPServiceCallback, O# _4 T2 q/ V! ^3 W0 _, k: ~9 R
{* z2 |/ y. Z6 `! H* ~
public: D! Z; k& Q; h: `/ e( H
CServiceCallback(CUPnPImplWinServ& instance)3 o. v" B* e. h! j! n. M
: m_instance( instance )# A6 e# f' [ I! @# c6 ~, b3 t
{ m_lRefCount = 0; }. ?6 ]3 N' i+ u1 O L; D
3 {0 f8 _5 ~7 ]& G
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);) N+ u- p( T$ x( ^* B
STDMETHODIMP_(ULONG) AddRef();
; ^# p# ?) s& s$ T! n- f STDMETHODIMP_(ULONG) Release();! }/ k+ q! t5 m7 f' a3 [
6 |0 i# I- s3 F2 I, s
, t" F0 i$ s" r3 k0 c+ X% p// implementation
/ w3 A, g1 e# B5 jprivate:
* m: V: h8 [+ s! h HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);
' g6 _: U! `& E8 {/ i5 _ HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);
4 Z* e1 V: R# a% `9 H
# B! d2 v$ p; U& C c! s- M1 `9 N! l5 o2 N
private:: Q$ Q Z4 k& q# r, Y
CUPnPImplWinServ& m_instance;& H) _7 A' m* |. _- e
LONG m_lRefCount;+ R1 R9 E, {2 k6 m! j
};8 c' l6 l7 V: d% p
$ J9 i" Q9 I, P1 p. v, d& Z8 x0 n! k4 |9 U' k7 Q; e
/////////////////////////////////////////////////2 [! e, H3 X. B: l% W! F
: h$ }$ W: e0 P X8 s% ^3 W( \! F% _! {2 C( f# Z. I* P, A
使用时只需要使用抽象类的接口。* ]3 B8 h7 W i) X& c" T0 w& F' _
CUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.
, y9 {/ h/ O b9 O' A" {$ f! c8 K7 ?CUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口." |! ~1 z9 W' y' n7 A1 g, z
CUPnPImpl::StopAsyncFind停止设备查找.
# W! E4 Q1 _$ k$ u+ GCUPnPImpl::DeletePorts删除端口映射. |
|