|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule," @8 P- @% t5 h: }) Z; A' _
- _9 B* X! V3 \/ P6 i
" U, C1 o0 D6 b
///////////////////////////////////////////
! z* z' Z( T8 H p# P D3 S//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.
7 l/ G9 }2 ]6 R, s
: k$ @4 K# X$ G% ]6 v* R- @% r8 @$ _! z7 E! J( x, x; N
#pragma once
, V6 W% @" J6 }1 Z C6 V#include <exception>7 J4 W5 k( H( C/ z& z8 q k
$ o( H/ y8 ~7 W+ Y, z+ o" j6 w" h0 J8 F, A# n
enum TRISTATE{7 L0 w1 U0 Y! n
TRIS_FALSE,* x( h! L/ i" z7 P) d9 I1 L
TRIS_UNKNOWN,
( u) E' @6 D. K8 v, W9 e1 v+ T# Z TRIS_TRUE$ Q' W! C% B7 O& ~1 x$ @6 M
};+ k, m& u2 s# e5 r6 U
/ h# x+ a$ \+ v/ O: [3 ^
3 n$ `0 n4 H+ Q3 Y; c5 v
enum UPNP_IMPLEMENTATION{
+ j# b8 J% a& q& n UPNP_IMPL_WINDOWSERVICE = 0,
3 |: {2 b" v# G UPNP_IMPL_MINIUPNPLIB,4 Z7 X: |6 ]& C: C& M0 B
UPNP_IMPL_NONE /*last*/; o: O2 L0 i$ y: ^4 g! Y
};
" e. A+ N1 k: o7 G* v2 Y! H4 z* q9 C7 G; g
, X; ?5 L3 K/ J9 F( n3 [! I
- w, } h- Q5 l ]8 c- ~/ ^4 A
% \( f6 R- m5 A' z, g
class CUPnPImpl
# V( m% r& k- j: P{2 W/ }/ b: A9 L( _5 K! y
public:
% ]" K- o- ?# n CUPnPImpl();
% n. J; s( y$ G/ W$ l virtual ~CUPnPImpl();# e) I( Y; m& ~% L
struct UPnPError : std::exception {};
) T6 b0 O" P5 h( t( } enum {0 W2 w8 r+ z% L% f+ N
UPNP_OK,
" p: f2 T8 S2 @3 b UPNP_FAILED, u' b7 ` I0 h( H
UPNP_TIMEOUT0 w; v i6 ?' a( _, t( w
};
3 c, }, Q/ [( T% t; S" d h1 Q& i6 P# m; ?, M; t7 V
$ J; g! K, E! j* j0 d* `: N virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;- {5 m& Q2 B8 Q0 ~
virtual bool CheckAndRefresh() = 0;
& [4 C4 n8 v1 y( ^2 } virtual void StopAsyncFind() = 0;, A6 B- v. ]( b+ n! G6 i( Z) { P7 ~
virtual void DeletePorts() = 0;; j: W% f) F) ~3 P3 t2 r8 J
virtual bool IsReady() = 0;
- Z9 w4 z+ J' ]% \6 f- x) v* h0 A virtual int GetImplementationID() = 0;
0 ?- l ]( t+ W' y+ h$ C& ~: {
- @! o U$ P# u/ ^4 a6 H2 A2 ]/ Z void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping
, {9 @) f! }! `+ ?2 v4 K8 P: A) \& n! i8 o- ]0 y9 B) L* |: \
: B1 _- o; _( X/ U- s6 @* m
void SetMessageOnResult(HWND hWindow, UINT nMessageID);. r- V7 M8 d, W: x+ q# ?
TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }! Q8 m4 f: e) m U+ b/ W
uint16 GetUsedTCPPort() { return m_nTCPPort; }
/ V# A; O- W( u; s5 W* h- [' o8 B uint16 GetUsedUDPPort() { return m_nUDPPort; }
6 D' K4 P* ]9 a/ Z [+ J3 T. y2 l k" @2 T* B
; W; M# R9 G" C7 R// Implementation' b6 a4 R1 |& B( h1 J* j, x: R' @# I
protected:; m( b- @( F* ?" j6 B
volatile TRISTATE m_bUPnPPortsForwarded;7 [1 `9 C% r7 R$ Z9 f
void SendResultMessage();
0 o+ q3 y: b! c uint16 m_nUDPPort;
, g8 _6 i4 `, `/ j uint16 m_nTCPPort;
- d7 ^$ B, Q3 p% m- Y6 ^9 r uint16 m_nTCPWebPort;; }9 i8 T: q" v& ?& @. h
bool m_bCheckAndRefresh;6 Q, X7 `7 G" r9 a
/ w* c2 ^6 h# _6 ~" U$ b
/ _; b* U& E% h( {% O. bprivate:
: ^ \+ Z& R0 R HWND m_hResultMessageWindow;
" L7 ~' }2 R) N9 g( K/ X UINT m_nResultMessageID;* A" S8 _1 M2 k7 s) G7 p5 ?- u/ y: m3 d
# C& B& `# j% D9 D4 F5 R' p& }$ P: i
' @5 v- g: }% Y' G: I! q};
$ W- j1 W+ F+ N- ~ ~# Q8 w3 }! T
2 M1 c. @1 h, O6 c& p* b// Dummy Implementation to be used when no other implementation is available
! J3 h+ Y# a/ m( wclass CUPnPImplNone: public CUPnPImpl
! Q+ `9 M( Y4 z{* W% }+ ]9 k% |- [; I8 d4 S& ^
public:$ m* f' L& ^! Y, i b$ h$ N
virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }
2 `: n; ?) o5 |3 W virtual bool CheckAndRefresh() { return false; }
3 a H9 [4 }8 h+ p# z virtual void StopAsyncFind() { }: Z1 Y% a$ Q/ o' ?/ I. M' q
virtual void DeletePorts() { }
! q: d* p1 s: Q4 _* a* b( N virtual bool IsReady() { return false; }+ V- l" p8 d6 U1 c- ?) R6 w
virtual int GetImplementationID() { return UPNP_IMPL_NONE; }
2 j: F4 N- y# p$ k2 _( C7 D};
+ l2 D( V* m' ^" U
3 r* d! }: b$ T: I2 H2 E7 _. w Q* t0 k& r; v; U- w0 r8 p" p
/////////////////////////////////////
# z8 t% @; n$ { N( V2 n# V) n& ?//下面是使用windows操作系统自带的UPNP功能的子类
6 f' G4 R& |+ y3 b+ b% z7 m1 L% O9 L0 a) I# y- ^7 B
2 P6 m) y4 V& I" w
#pragma once
, \, W S- ]. N$ j; N" L4 p#pragma warning( disable: 4355 )
% ~6 }: |7 w( w- @" t- Z3 n$ y% p5 y4 H- ]
+ D$ C+ e7 A! Y+ t ~
#include "UPnPImpl.h"
1 S i5 W, \6 H0 J$ ~* T#include <upnp.h>9 t0 L! n% b( N8 M" k' U( j
#include <iphlpapi.h>
8 ^; d0 }1 L, e' V+ W7 E! w#include <comdef.h>* A, d1 p( q' E, u/ ?
#include <winsvc.h>
- Y; h( r4 s+ z2 l
% A) Z L/ F* u. S. _4 Z) G0 B/ s5 s7 D' z2 E2 }0 s0 ~! y& x
#include <vector>. m7 _! k% i+ h3 ?' `- M- k0 \: H
#include <exception>
- E* K5 i% i5 x) S' T#include <functional>5 F V1 v* S6 ^" g0 g
2 H4 r% m" u4 ~$ {) h! Y5 r/ G
$ `* B/ ]# r- [" r- J! m) h! Z
# r" _; i3 A9 ]; z" a
$ E) V d. b1 G$ a7 ptypedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;
- P6 @; _5 E# z* Ctypedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;
5 q' Y) u9 @. z+ k8 P6 y" f+ p7 ttypedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;9 b( b) ]0 v8 }, @, ~6 v% ^
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;
' m% `+ H8 I5 {1 S* U6 K6 qtypedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;
2 f: o5 z+ `; ]9 ?typedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;3 t! W; ]8 e) L! C2 v
typedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;
; }2 C# {3 U% C6 _7 E' _+ e
8 x+ P, E1 Z) ~, B
F1 T9 q* O( rtypedef DWORD (WINAPI* TGetBestInterface) (8 z S1 f! G/ A% D- l& p8 p
IPAddr dwDestAddr,
: P. y) h% K5 F0 I% A/ c PDWORD pdwBestIfIndex
3 d, b, m3 I% });
, c: h/ t2 u5 X' _9 z. u! ]
- `0 r( H, b. f) V% [) X; h- I5 r- E9 ]
typedef DWORD (WINAPI* TGetIpAddrTable) (3 L1 [) N8 r& C4 A
PMIB_IPADDRTABLE pIpAddrTable,2 Q9 }( f! ~( C: W) ?, |
PULONG pdwSize,
; X; V, A# o& T- Z; A# d; j. P BOOL bOrder1 }5 t5 k+ M1 m6 [5 x" l" R5 g. G& ~
);( b) T" S! O+ o% x6 a3 E
' E! f7 H& q3 k
" U9 w4 h+ \# A" vtypedef DWORD (WINAPI* TGetIfEntry) (7 j' Z7 P& l5 c! H7 |! v
PMIB_IFROW pIfRow; `3 z# d8 r7 c; G
);
8 W: x* N& X, |, O
$ T- I+ p+ Y i; J& }+ }% y! k/ ]3 L) ~/ V: T5 ]
CString translateUPnPResult(HRESULT hr);
# M& U* Q7 W( lHRESULT UPnPMessage(HRESULT hr);1 E9 S! {# y- o& L+ x* l" M4 E
; e( e$ B- w" i( B7 f' ?* S2 ]0 Z+ B" V) }& q
class CUPnPImplWinServ: public CUPnPImpl
1 x1 W+ i$ r' n- a% Q* p( e& a{
3 f' A( V7 k7 F+ x friend class CDeviceFinderCallback;
/ b" D3 l# _1 D% A8 A! r- U, u friend class CServiceCallback;
* k/ G+ O8 M( b" s8 ?% X! q; h// Construction
! W! |4 O) @9 N1 c; Vpublic:% D* o: _+ `5 Z0 t
virtual ~CUPnPImplWinServ();
$ b5 P( G' Q0 t& k. \ CUPnPImplWinServ();9 K* O; s( w8 |; N, S$ K7 q2 T' `
/ {+ d! L- H4 p3 y J6 q- H2 d5 h
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }$ l! w- p" l* n1 \+ X! l
virtual void StopAsyncFind();2 T$ b# _, K) |. d1 E9 a
virtual void DeletePorts();# E9 t S, x- {' R
virtual bool IsReady();% r6 C1 }7 [+ X
virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }
4 I1 M6 K: G9 h/ `1 r
( ?" T+ X/ p7 p7 v: E( d
* ~! r* _4 e: \+ p' P4 O // No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)
2 [# W) |1 e! f: z // the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later- }, L% ] P! X; {3 L7 K6 L
virtual bool CheckAndRefresh() { return false; };% z$ G" \6 s$ O; o) N
7 n5 |; F$ S" o9 B% z7 W4 I$ b- |
' A! y0 Z& |: D: q1 X ~, jprotected:3 J% I; F H, p7 s ~0 _1 P
void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);
' G3 d: \8 X& _ void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);) A, z/ N5 |7 b& q9 p
void RemoveDevice(CComBSTR bsUDN);
0 `" D: H& b$ ?2 g& u bool OnSearchComplete();. B- d( \; \ x/ i2 }: P& @
void Init();
4 g1 V; H, l$ o6 h/ n. z' Q* @% Z# g; C, [
N( k& B" E6 @4 {2 | \ inline bool IsAsyncFindRunning() ( X$ H! n4 |1 `6 a7 V
{
0 Z7 v( h0 u) W if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )
P" ]/ }+ Y3 q7 o {5 s r4 t+ Y8 I3 S5 {& ]' k6 Q# H% S
m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );
8 l, P: J/ [7 q6 W# P6 d6 J% ?; k m_bAsyncFindRunning = false;- L8 N- e8 q* q; Y% l3 _# r9 {
}: d0 o& T( h2 N/ f! [3 c9 F
MSG msg;# C U! E- S+ [( g. o
while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )! ^( f. A5 q6 V0 u
{
" q" }$ e/ h4 R) X3 ~ TranslateMessage( &msg );2 _7 x0 V( a/ W( [7 m9 }# ^) w6 j
DispatchMessage( &msg );7 e6 Y6 c# y: S' G( e
}/ L, v. b8 A$ B& o; ~
return m_bAsyncFindRunning;
- B3 o U4 g" _: f$ Z }3 x4 k$ [1 _( ?; z' D3 | [
( s3 V6 p4 O4 I K% Q* l" y |3 G. p0 {& L# v. I, e
TRISTATE m_bUPnPDeviceConnected;* L3 B7 @8 G0 r+ ?$ Q
W9 \: y) [- Y4 v4 H
5 X, j: }" U" }// Implementation
" p& w6 t3 s( L s! f5 ~- x // API functions
F0 ?) s4 b4 N! S. H SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);+ j+ e' ]0 K7 T* {( b, `4 V. M
SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);
$ l* z Z6 i2 n0 G6 s% r BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);
$ _" o$ J. T% z' M. U- Y) r$ a4 \) C$ I BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);# c) u8 p* \8 b4 D2 D% f
BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);" {- x3 i: y. a0 o
BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);
' @* j9 f7 q% U" j/ A5 _* j* l# M w( D, d& i8 G; E7 E7 a [
0 }: ^" ~, V, Q4 C* D
TGetBestInterface m_pfGetBestInterface;
1 U/ v, [, g: X: X9 x' v6 C TGetIpAddrTable m_pfGetIpAddrTable;5 h, e1 a- E1 x$ m
TGetIfEntry m_pfGetIfEntry;
/ G. H" ~/ b1 P8 f) t# h' q
; c3 K$ X3 B" M# W8 H- |& k- N% r* X4 o% ^
static FinderPointer CreateFinderInstance();# U# {' h8 J9 p- B4 c6 S% w3 ?
struct FindDevice : std::unary_function< DevicePointer, bool >" O' G- n9 h' [
{
0 X2 ?9 \# `. L9 e. l$ S/ q- a& V FindDevice(const CComBSTR& udn) : m_udn( udn ) {}" p2 u# P, S" l S' L$ J
result_type operator()(argument_type device) const" K( [7 L4 W$ ?! y' Y M
{# `/ L& ~6 u' Y6 @! s0 r
CComBSTR deviceName;
( n" p( i3 c+ h3 C* B HRESULT hr = device->get_UniqueDeviceName( &deviceName );0 X# t( t- b( x, F1 F
@: H/ d w7 k; m1 C. ^: D$ J) K! Z$ I& L
if ( FAILED( hr ) )) O& u- Y l) @* Y E) l4 u
return UPnPMessage( hr ), false;0 I3 S4 o* {# o, N/ B
% B- F8 u3 A$ d4 r! S
( `( Z* d; l9 f: O4 v$ ? return wcscmp( deviceName.m_str, m_udn ) == 0;
3 e, b1 I& @; ^: g4 u* K }
9 k4 X5 O1 o, |( w CComBSTR m_udn;
1 g" ^7 g- b. b" w2 @ };
e: q( s+ |5 [& @, f 4 j3 L* D+ \! `! f' Z
void ProcessAsyncFind(CComBSTR bsSearchType);/ `2 K% M0 w; v% r
HRESULT GetDeviceServices(DevicePointer pDevice);. \8 v2 D* R4 t
void StartPortMapping();/ d8 p& {9 ^+ [
HRESULT MapPort(const ServicePointer& service);
9 t8 d4 M0 K6 r: i2 a" D1 U void DeleteExistingPortMappings(ServicePointer pService);
+ Q6 e6 y4 O' l; k void CreatePortMappings(ServicePointer pService);
: T6 k0 z3 ]; Z HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);
' e9 r6 l) U5 }; ]' d. t9 o HRESULT InvokeAction(ServicePointer pService, CComBSTR action, * [; Z9 A1 b- Z* i! T* x
LPCTSTR pszInArgString, CString& strResult);
% E+ l4 ~ \2 C7 ~# K) k7 e void StopUPnPService();
/ h8 @/ q5 d+ L& Q8 k" r% V
8 A4 T# n" c5 @6 D" a3 S B
! {8 h* F* v4 B( g! s // Utility functions- {& k* Y' u: |5 d; j9 A
HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);
( j/ X9 H/ t# a7 G1 N; l3 p: G INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);
7 f9 G; i, k# E& S& H INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);
# I6 `' K, }6 d! C5 g( p void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);
. | l3 e1 X8 g* q HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);
! h. d$ Z; N5 n: J) V HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);' W {% k# |$ H$ v- [
CString GetLocalRoutableIP(ServicePointer pService);
/ d: f3 B% s; ^& X6 K6 W6 ?! \* e. Z R
8 n2 H; }) [0 c' d6 j
// Private members
! W1 t% @6 l6 s: ^6 D3 Yprivate:
3 |( D% n' ?8 j j6 B! m# s+ v% o DWORD m_tLastEvent; // When the last event was received?
1 X3 W2 ^: s8 n. L std::vector< DevicePointer > m_pDevices;3 g2 J& ~8 {! a( M, b' E
std::vector< ServicePointer > m_pServices;; v+ a7 X2 ?% u1 x& F/ r- G
FinderPointer m_pDeviceFinder;3 @8 V" C: k& e
DeviceFinderCallback m_pDeviceFinderCallback;1 {1 \8 z t# ~# B) a. j- B: l
ServiceCallback m_pServiceCallback;
# H! @& R% R& G- o0 X6 s1 T% R E ]! u A& A' I$ E
# u5 J/ l+ Z) I9 ] LONG m_nAsyncFindHandle;# H- P; H. X. E: q I$ q
bool m_bCOM;- W# h5 L) p6 w
bool m_bPortIsFree;
! d5 U* s- h, G, E/ F# ]4 g0 m2 Y$ J CString m_sLocalIP;, x# Y1 I! B: @1 L3 L* d2 ^0 }- }
CString m_sExternalIP;
" R5 V: K& i+ w9 S& n2 R bool m_bADSL; // Is the device ADSL?! ] U+ v: V6 o- z1 m4 r
bool m_ADSLFailed; // Did port mapping failed for the ADSL device?8 P- l" n+ m% i* o2 K
bool m_bInited;
0 h: J: k3 z! V3 d6 E0 P1 W bool m_bAsyncFindRunning;
( ^. b) `, r' G) J( X/ W& c HMODULE m_hADVAPI32_DLL;
* j; \! _7 o0 G+ \ HMODULE m_hIPHLPAPI_DLL;
v# _1 g2 Y' T" M/ A! V( K, y. T bool m_bSecondTry;3 j0 z C: {( D% E
bool m_bServiceStartedByEmule;
: h5 y+ \5 p, P+ {4 g bool m_bDisableWANIPSetup;
8 r" M y% ?% ?1 t/ X6 M bool m_bDisableWANPPPSetup;/ O% G6 r& ]1 w. a4 R6 S
. Y7 c$ p/ q1 ]7 ^5 g9 ?3 H) x/ o$ I/ b
};( Q8 M/ a/ n8 u6 R
& I5 U3 u6 \+ W8 O
6 z0 ]( _9 w9 W. l' }
// DeviceFinder Callback
! y# k S7 g# E! _class CDeviceFinderCallback @9 L. {, O' C( `
: public IUPnPDeviceFinderCallback: k7 ?) U& ?+ Y$ ]. W5 b
{
& {/ C: U$ e; L9 g. p7 F) a2 Ipublic:3 s8 ^8 D4 j8 E# ]) C# x- Y
CDeviceFinderCallback(CUPnPImplWinServ& instance)4 c8 W! u5 p3 r% g4 C" D) x6 I" ?4 O( m
: m_instance( instance )
4 \. W8 B+ Q' a b { m_lRefCount = 0; }
( _* F) n9 C4 @& d3 \5 F B$ p9 J L: D) u i+ n
/ r: B$ s7 y$ @+ o7 R3 K6 h
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);5 ~5 u9 D2 N" p9 J, L- }
STDMETHODIMP_(ULONG) AddRef();
6 {/ b; f$ E- H% j# ` STDMETHODIMP_(ULONG) Release();3 D8 a4 A3 @% `, G1 V7 l. I& F
' ]( k0 ]9 e% K: E" `* }
( ]' O1 J7 l1 H; N8 D9 Q
// implementation
4 {5 x, Y, G" u+ x) [$ v7 H1 z: xprivate: K! X1 |/ s: x9 _. ]" a
HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);# G+ P# `" ^2 \
HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);& B+ ~' v: a, A/ ]
HRESULT __stdcall SearchComplete(LONG nFindData);
# }/ J/ v' ?8 H' |
1 [3 ^. S. I2 T, m2 g: e/ U7 x
! V& }+ A% U% Z5 L# w& @private: r# n& o# Y# Z8 Q! ^0 I
CUPnPImplWinServ& m_instance;
% T$ [7 n6 ]# G; \7 V* A: c LONG m_lRefCount;9 B/ X8 b5 V0 J7 G
};
|) N/ M' R# b2 k) p, F" e
# B9 ]* _. H N* V4 q6 h/ G' i2 \5 f A: f# S( g8 s2 }
// Service Callback $ n9 b$ f( t/ X9 s; D7 ^, y0 T
class CServiceCallback
( r9 K! Z2 D3 p% }9 X. p6 i : public IUPnPServiceCallback
$ U2 A9 K `0 \/ c{
# ^' T& j R. s5 e1 |9 upublic: }1 {* [8 n0 M/ j% Y1 r
CServiceCallback(CUPnPImplWinServ& instance). L; ]1 r' F. H- Z' u$ F9 O
: m_instance( instance )2 c5 v* @/ r, M# a/ q; l
{ m_lRefCount = 0; }3 j3 v& d3 Z# {" a6 Q D. M
! P) ]* D& K; W% o, t
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
8 @" s6 q) c( ` STDMETHODIMP_(ULONG) AddRef();( Q# ?& I9 ?$ f3 C) [
STDMETHODIMP_(ULONG) Release();
' p4 m- n; _) C) V- M% l4 A$ ~* J
/ n3 f" h; K6 _) i. k. m/ W2 `& F ^: j
// implementation
, y0 [" ^' ]) d! @private:
3 m# H; \" m& P* |! I0 t+ q0 A HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);4 U" d! ?# k y( K7 d
HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);/ U9 ~+ ~% B; B1 ^2 r0 W# J
' _! p6 K9 b1 s* X4 n
f5 Z+ @! W) M) ?1 t8 v& q8 bprivate:! p$ D% L( q3 ~
CUPnPImplWinServ& m_instance; G* v& U: c3 z
LONG m_lRefCount;
6 Z2 w" C! ~" b3 @# w& i9 O# ~}; l4 Q. ~0 p+ v/ j. d) z- r) I; {
% A6 X D* K5 J) p6 I
8 |) `( [7 V7 \1 g; w( p/////////////////////////////////////////////////
: H6 Z _7 i/ J. {
! f$ e" Y- u4 I; X9 B5 x4 O; d* Q% T8 k! i' q
使用时只需要使用抽象类的接口。) {6 f x+ U* M3 j: @) @
CUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.
( I; x. z$ A0 T% ]0 u+ W$ LCUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.
1 k5 W- t4 l* |! w+ }! FCUPnPImpl::StopAsyncFind停止设备查找.' |# L+ v% f4 m* _: \
CUPnPImpl::DeletePorts删除端口映射. |
|