|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule,. Q S" F/ d9 z) L! p7 K
' r5 f1 T9 n/ h- t7 c# V* n
! T1 }& q3 M" p( f) t///////////////////////////////////////////! v( ]7 \/ s* x! Y" E& N9 O
//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.
A# I% x) d8 y4 x' ~
# n* X2 u8 i+ {& v9 Z% l6 w1 m4 i1 _! Y3 T
#pragma once1 C7 N3 _- @; s3 Q/ d8 B q
#include <exception>
! o; t+ [" C0 Q3 q; [ ^$ U R( B0 m6 q
0 {! Y# @- D' i: `4 J# v( w enum TRISTATE{
# P1 F6 l0 E0 w TRIS_FALSE,
% q, u; w. e7 I# U TRIS_UNKNOWN,1 Y* ~& Z' `) q p# C
TRIS_TRUE
7 E' s. B1 J& y7 A};
, ?) t$ d, T! D2 W+ |3 e9 x+ j1 C4 ?! X+ k
! {# S( u+ d$ W, ]4 l
enum UPNP_IMPLEMENTATION{; y' H% N8 R) C& [4 r
UPNP_IMPL_WINDOWSERVICE = 0,
/ f' |4 j8 A5 v5 n& V+ ] UPNP_IMPL_MINIUPNPLIB,
0 q) }0 L6 p. p& m) c, ` UPNP_IMPL_NONE /*last*/
6 l' F% J- t8 L0 M3 G2 v7 M};
& M: h d2 s# a7 r3 k \6 j* w9 M. d- P- g
3 O [3 p3 [0 h- t( ^
+ l r7 W. G' G, }" `1 Y% a; [ z- y4 v- a0 _
class CUPnPImpl
+ J" o/ R- V8 K0 Z% N( Y k& ]{
% ~3 n) u- \- Y: s: Fpublic:, x2 f! w1 z5 o$ o0 r5 S0 J$ L: \
CUPnPImpl();
: c! m4 ^, Q1 b0 O, h virtual ~CUPnPImpl();; k5 x% f C0 J: U% I0 b
struct UPnPError : std::exception {};
7 x. l2 H6 F1 C3 X& }: c. W enum {' g6 J1 h, V- M0 r+ M- i
UPNP_OK,4 ]+ f9 x4 f& v* D: a. i' Q
UPNP_FAILED,
, u" @' {* s: g! b, ]+ z3 n: B6 _ UPNP_TIMEOUT
; p& H8 x" }) ^0 q4 Y };0 N* V: p2 h N# v! M/ A$ h: q. b
, u1 V4 ?5 E% ]. d4 B
6 r- R4 o* X, w
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;
# v1 o9 c4 }1 ^( d7 u' U7 n+ q virtual bool CheckAndRefresh() = 0;
, @) ~# B1 s' K8 S& }/ k6 a8 i virtual void StopAsyncFind() = 0;& T; H A* U. |: m; x8 J: }! L! I% h# _
virtual void DeletePorts() = 0;
6 }' w# w0 V! [8 a. ]( y: | virtual bool IsReady() = 0;3 I% b% d! r# w7 Z" `5 v+ i; K
virtual int GetImplementationID() = 0;
! ~0 A* q' p- E" U6 ~
- l% C3 Q7 s0 L( s Y void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping- s+ \7 T- S/ Y0 O& G& s
$ P* D2 ?$ w8 H! E2 _# ]
! G9 O* s/ d3 d4 [( z void SetMessageOnResult(HWND hWindow, UINT nMessageID);9 H8 }/ P% T, D1 H2 _
TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }
, u/ m& |" T2 X uint16 GetUsedTCPPort() { return m_nTCPPort; }
" ?8 K+ e2 H1 P8 { uint16 GetUsedUDPPort() { return m_nUDPPort; }
7 l. b G1 ^6 g9 b7 J$ G \3 d
$ F: i# o) B9 E n4 u2 W8 N: R' q: P( g& r4 W3 U
// Implementation6 U. J, l2 N7 d2 f
protected:$ p! J# h1 f5 V
volatile TRISTATE m_bUPnPPortsForwarded;
) C4 ^" B% K1 B4 p void SendResultMessage();
2 H6 |9 w& ^ t- f5 U uint16 m_nUDPPort;
+ v% X/ m) C+ f& x5 U4 n uint16 m_nTCPPort;
7 ^" p5 i* _6 V uint16 m_nTCPWebPort;
3 B: Q) Z. ^, x* i bool m_bCheckAndRefresh;! m8 R _1 m \5 R* ]) ^
/ s' t* H1 q/ b
. q7 s$ p! R1 E+ Z- q z
private:
. z4 n& a! S2 S" [ HWND m_hResultMessageWindow;" g. v7 S3 U5 ]$ W* }/ n8 B. c
UINT m_nResultMessageID;8 Q+ w7 Z" J2 U6 o. T
1 P8 F3 T/ `/ K- u2 B6 x& N% P4 X3 L
6 @3 c, N# @1 H" F0 w. {};
, j1 P* a1 H& j# F6 V9 W7 `5 @
: W6 c0 N# U8 S3 h4 a- v- q) L5 d. {' }+ x3 `4 x
// Dummy Implementation to be used when no other implementation is available8 U0 l, F! I: H' z: y2 L. @
class CUPnPImplNone: public CUPnPImpl% h& U& x/ _. c/ ?( _! i2 ?& W2 r
{
. u4 }9 w3 k. {* Xpublic:- U1 ]4 e1 B l
virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }. |0 f/ w3 \& S
virtual bool CheckAndRefresh() { return false; }
$ [, G$ ]9 o3 @! o virtual void StopAsyncFind() { }$ o. X6 x3 f0 @* z
virtual void DeletePorts() { }
' |% I5 t' b! w" z virtual bool IsReady() { return false; }
5 m$ u, O( L H) p5 Y" E virtual int GetImplementationID() { return UPNP_IMPL_NONE; }4 _+ `; F. A! o
};
$ G. _- a6 h x2 f* i5 z+ F \8 U4 y
7 |. l9 h4 j( Y8 l# [: a& |2 t///////////////////////////////////// t" A9 O% U% d. d
//下面是使用windows操作系统自带的UPNP功能的子类
1 t+ k1 }2 ]9 h7 I0 Y9 A0 Q
. n4 e n) T# g5 O# s. x( X& v" v& S% P
#pragma once
2 v( A _; \+ J+ e; g9 P#pragma warning( disable: 4355 )
# x- j; _+ X- A' P3 F- f* f9 ]: ]3 I4 x: n7 y3 B
' b6 c0 l, x2 P/ [2 J+ g# }6 `
#include "UPnPImpl.h"; e8 b8 j! Q" ~# X( F" U% q
#include <upnp.h>( z0 Y: t' u6 U) o
#include <iphlpapi.h>
1 b. |) T# K4 _% c2 z, i, w#include <comdef.h>6 K! M7 z, B* M; j. ~
#include <winsvc.h>
. v7 |) ?+ g: I8 S7 `0 v( @
' b- X, `6 O, ], z$ J! j, Y- Y9 T; W7 {, m+ f
#include <vector>
1 H8 X) L; B, z#include <exception>% P" c, P2 Y8 H3 N# q' O
#include <functional>) I" M7 H% y- [
; K1 _. n% k# V8 G/ z( e" k/ D. y3 |8 U) s% {8 K( S
2 m1 ~! _- _5 K! U0 ], g
3 M7 ]- _/ e6 P2 i0 y& Btypedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;) ]/ l. ^+ a9 X% W( e9 z4 f0 Y! V: c) }
typedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;
' \" o; ]1 x, otypedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;
9 l4 m& [$ i( f# j8 e% Ztypedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;
4 U8 D k. R5 c: V& g8 z- `typedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;$ F6 L+ Y9 G% m3 J/ A5 e
typedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;* O( c; M( x1 A9 \
typedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;$ j: v! D$ Z! f1 B
3 d8 T! K/ @) J! H7 c* y
2 v2 N! m4 b2 V. c3 t
typedef DWORD (WINAPI* TGetBestInterface) (4 {/ x2 l. M/ m; n
IPAddr dwDestAddr,. n! t3 Z+ Q" v! ]# x4 Z! g- ?& m
PDWORD pdwBestIfIndex9 @' C( Y, \# i3 G
);# y) F+ V; W5 ~' g% R3 X. q& ~ K/ f! m
( F) [6 V, N' H2 `$ e7 F! f$ V# L! W$ a7 q
typedef DWORD (WINAPI* TGetIpAddrTable) (& z+ R* s: T1 _: v
PMIB_IPADDRTABLE pIpAddrTable,
' h9 q7 L& V# S4 q1 W* Z( g7 Y PULONG pdwSize,
0 j0 b- |% k1 \( s2 S/ j5 h9 S" T, L. T BOOL bOrder
- p3 G9 X, E: a! _. j3 \$ });/ P8 ~, r% {' ~; ?( P ]* u9 w. f
9 Z1 w1 p( c8 H5 S9 ?
* P7 p/ y. f1 S/ Qtypedef DWORD (WINAPI* TGetIfEntry) (# p# H! N+ p& p2 n, Y
PMIB_IFROW pIfRow# k8 U6 y+ E7 S9 T+ G! d# q, h; L
);
" [: z+ j) X' E/ F$ c
7 X& G" a1 g- k& ]5 r
- B% j3 t0 {$ J1 PCString translateUPnPResult(HRESULT hr);
" @; ^ Y# N* Z& T' l4 ^HRESULT UPnPMessage(HRESULT hr);
& V# d& L" `* t3 [
! d( ?( P0 u; p( O8 @4 o6 G# M1 y0 g; Z) A
class CUPnPImplWinServ: public CUPnPImpl
x4 Y# ?& L4 d5 \{
7 @/ n% h9 ?. i friend class CDeviceFinderCallback;& D I- @. g& `/ H+ O
friend class CServiceCallback;
/ B& { b7 L8 l/ D% x+ ^3 N// Construction
: @+ e" j( J/ i4 {! s! g# z1 cpublic:
( Y/ A }) m) D. U: M virtual ~CUPnPImplWinServ();
! n# |1 F1 X f# c( s9 T* \& T CUPnPImplWinServ();
5 o o2 u( c& ~! \. K! `8 { m- l3 X& ^/ B4 {3 {
/ v, t1 E( }0 ?/ `' _, L
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }6 B8 f$ b g6 {4 p$ f
virtual void StopAsyncFind();" V2 c9 K8 v+ u" B5 P
virtual void DeletePorts();
# R* x2 N4 T0 o) s# t9 d6 m, w virtual bool IsReady();
% R3 i3 v; o8 f* L# B5 k6 ] virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }
; @% F7 i' _: Y" w" x! T/ R
; l# I+ e8 L, K1 M7 `
: C4 j* l" ^ e) Z // No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)
/ T8 N" A+ d% _! R- R // the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later+ g& Z+ u% f( F% Z
virtual bool CheckAndRefresh() { return false; };
( x- M" W: ^2 D, J/ \
! V' D7 p6 h' h0 K! }# @: B
) J5 Y, v, V1 G1 d4 Cprotected:
: ]+ I7 `$ k& Z0 }" G( W void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);
6 E5 h% w/ ~: j: ^" q4 n% D$ H8 B# u void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);
7 t, I+ _) ^0 z) s; d3 Y& V void RemoveDevice(CComBSTR bsUDN);# c$ t1 u; M* K9 Q3 @$ q
bool OnSearchComplete(); e5 j1 g$ X" A& y
void Init();/ s# J$ Y t! A! I: o' o1 }6 w! V
& |: V& I" Q4 [6 y" W/ k2 X, E: e% S
$ K0 X! j2 M, x# P! E `$ C
inline bool IsAsyncFindRunning() ( i3 J( M7 n. O
{% L2 V# y/ H9 C$ H) l9 N8 s O* R
if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )
& V: K! j/ G. |+ E8 U {
- P3 M9 |: b# c% d) g# o8 L3 p m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );
4 j8 ?/ i* I4 y/ T) F2 v7 S$ C m_bAsyncFindRunning = false;
; q( i W/ ^- x6 z+ c }
; a5 {( ~8 r% N$ d( A MSG msg;' @# J6 B/ w; ~* y( }1 r/ v
while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
* T/ U- y9 k! t+ v2 b {2 v6 T9 R7 Y, I8 l% ]" G
TranslateMessage( &msg );9 D" [# }# x0 e$ X( O
DispatchMessage( &msg );7 A# ?' m" ^# a- A# x
}( ^; m5 v& u' V8 d
return m_bAsyncFindRunning;
7 S4 |4 d N6 b2 ? }
4 {# C2 A& n" n2 N- Q
6 ~! i- U. w# T& `. b3 J @( Y* D$ \. S, l9 ]
TRISTATE m_bUPnPDeviceConnected;5 [" `2 i0 g$ k) Q& \; E j' d
1 P* U5 s4 k3 o3 k
" k0 c$ t; K5 r1 n# L// Implementation6 L- N5 P" t9 w. \
// API functions; _. ^" R% D F2 u& a
SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);
7 h4 q. M0 |% o. }) V SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);! Q. c7 R: @/ {& J$ ~
BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);
3 u) U6 y* E( @: P/ Z- C" Q BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);
+ c: _1 |* Q0 u( z BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);
W4 I" D o7 [8 H% E BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);9 ^2 \/ Q6 T6 B4 v! n* E
4 Q& ?3 Q* K+ w: B, P! B: ~! [' X4 V0 H1 L) E$ Z% p
TGetBestInterface m_pfGetBestInterface;$ {8 |; F9 I1 q
TGetIpAddrTable m_pfGetIpAddrTable;
: x! z. v3 g" h6 I$ o# f3 K, z TGetIfEntry m_pfGetIfEntry;
! I! d& _: d/ c, ]/ p, x2 @3 P' f0 k2 [
; a' a0 i' H- N- _) ^- }
static FinderPointer CreateFinderInstance();9 u$ [: d8 E% B! u5 c3 L' l
struct FindDevice : std::unary_function< DevicePointer, bool >4 o8 d2 N' {" Q0 X: n: O# C
{
5 w$ c7 G8 w* A) s* ^ FindDevice(const CComBSTR& udn) : m_udn( udn ) {}9 |- M2 {3 A: s8 n
result_type operator()(argument_type device) const
+ F( i% x4 @3 k {8 }2 b) ` r/ U2 V- x6 t: x) j# G
CComBSTR deviceName;
- E, {' B) d6 M HRESULT hr = device->get_UniqueDeviceName( &deviceName );
6 P- @" R! F; S* E4 `" }+ S
2 w, k9 O+ |& ?9 X6 B [ N! _8 L
+ `% h1 V- J6 q3 P6 { if ( FAILED( hr ) )( s9 Z! h$ I/ Z! V2 l0 d: `/ D" C; V
return UPnPMessage( hr ), false;
/ |; E% @" b, [$ A3 Q/ h+ R4 n* q* T4 ]) R+ Y
7 [% c. S Y* W" `( x; K return wcscmp( deviceName.m_str, m_udn ) == 0;
* W6 ~9 t+ N* ~7 g" G& ?6 F }
, ?: e- u% h( }+ o9 F$ T CComBSTR m_udn;- @, {8 s8 e# \4 \; f
};
/ k# ?. e& K! N5 T9 w; b7 A. ? 6 S: k5 |7 I. `
void ProcessAsyncFind(CComBSTR bsSearchType);2 ]' T5 w/ _% ]
HRESULT GetDeviceServices(DevicePointer pDevice);
9 w( |" L3 S: J; j& j% U void StartPortMapping();/ [2 |7 j- ?( J7 }& l5 t$ g* w
HRESULT MapPort(const ServicePointer& service);
" \: \+ X- i7 D3 b& N void DeleteExistingPortMappings(ServicePointer pService);
% n4 G7 {' g3 |0 S3 d" t4 W void CreatePortMappings(ServicePointer pService);$ n; ]. C l8 L$ y
HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);
. I) @+ [0 H6 x7 B5 N HRESULT InvokeAction(ServicePointer pService, CComBSTR action,
/ I' K) f4 G, F2 X: h: E LPCTSTR pszInArgString, CString& strResult);, Y4 s5 |3 j% I7 d
void StopUPnPService();- H& A% [! |. U; C2 m+ ~( l+ n
% B' }6 q& W% F I
* C1 U8 e2 ], v9 i c3 X9 _
// Utility functions
& A; [, F i. }# C2 P HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);8 R4 o# g# g0 A
INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);
# g; Q6 I6 q: \9 J W6 k0 D. I( G8 S INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);* ^; `/ f& b9 _
void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);+ ]# P6 O; B: `7 \: f
HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);# P$ R- b4 m: S) s+ A5 Z
HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);
2 i) F* U* l: w) Z& d8 A% ~ CString GetLocalRoutableIP(ServicePointer pService);
% _, b; j" Y6 W Z+ S, {% T$ c' O, d$ i D
( E5 O' d4 i$ f1 e* W
// Private members; J. ~( W J! O7 W7 k) [) y% }
private:
U9 \" O% w7 t" ^ DWORD m_tLastEvent; // When the last event was received?
% d } ^- ~$ h& F1 f std::vector< DevicePointer > m_pDevices;& e! `8 h9 l' O1 g9 n
std::vector< ServicePointer > m_pServices;
( i5 A( i0 D S: R& q2 I FinderPointer m_pDeviceFinder;
! j2 a' {8 Q( V! @. Y: a' ^ DeviceFinderCallback m_pDeviceFinderCallback;4 r4 y% k( v/ I# m
ServiceCallback m_pServiceCallback;
4 {1 J& N* ~5 Y, W) y, \' H# ~4 c( m& V: D
& b# C+ `# M% M LONG m_nAsyncFindHandle;- e; Y9 a% {) i }" X5 x
bool m_bCOM;6 n1 @7 R+ W( U. h$ x( d/ X) q
bool m_bPortIsFree;# r$ ^/ A/ w* n D
CString m_sLocalIP; x: s& n* ]4 [0 W% a2 V, \, v
CString m_sExternalIP;: U; I% e9 w1 n8 S4 H3 t4 h: T
bool m_bADSL; // Is the device ADSL?% E+ x$ Q* J2 u" J
bool m_ADSLFailed; // Did port mapping failed for the ADSL device?
# g' Y$ ~% o- n$ p! s bool m_bInited;
# a- R2 ~* m7 y2 \1 i bool m_bAsyncFindRunning;
; H" S6 r4 u$ t1 G HMODULE m_hADVAPI32_DLL;0 o* s3 [1 T2 K [. @- V6 C+ _
HMODULE m_hIPHLPAPI_DLL;% f0 g7 s# j* O2 n7 t @' S
bool m_bSecondTry;
3 j: |2 X/ {/ s0 y6 D. Q% U* | bool m_bServiceStartedByEmule;
+ P6 M. e* k J/ P+ a- O bool m_bDisableWANIPSetup;0 r/ m1 S/ m( n+ A0 t$ Q. K
bool m_bDisableWANPPPSetup;
8 M- e) D8 Z- o+ Z4 A5 ^* S
1 Y; ^* P# A, G
. H3 F, B# ~" y) u7 v};* [2 Y! r" r N$ G/ X
2 l- n) \8 i; ^( I# ?, V
' R( n% P8 m1 T \, V' d
// DeviceFinder Callback
& W2 ~3 D1 ]% v# Q4 w( ?class CDeviceFinderCallback6 I1 y8 b0 V! ^$ ?0 Q% m9 m
: public IUPnPDeviceFinderCallback+ i7 f& y2 g/ h: { G5 ~
{- ^. _1 o- s' s
public:
; f2 u: }4 t( w5 O; g0 R CDeviceFinderCallback(CUPnPImplWinServ& instance), Y6 C- ?$ l8 j% T- a8 T
: m_instance( instance )$ l. \% J8 f1 `) v" A* v6 _( |) Y
{ m_lRefCount = 0; }! J% C0 |$ }8 g/ R2 Y5 R* S) A
2 p2 [/ H& ^( \, i
C6 }( y! Y0 N% L7 ?( t STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
! I4 L, k/ Z% Y) t+ O STDMETHODIMP_(ULONG) AddRef();
0 r; ~7 {& \" e# l* M, q STDMETHODIMP_(ULONG) Release();
/ Z2 ^2 W2 R- U
, O5 M( C8 m# h4 ]" j/ q0 }4 z4 }. u. l" {
// implementation
" o! X; C j I2 q1 hprivate:0 k$ l' }# K8 T% q+ k( W
HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);
! H. X# }# ^! X8 A" N1 B HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);8 b6 t" i$ v. W H/ b. `# t$ i
HRESULT __stdcall SearchComplete(LONG nFindData);1 ]5 t8 B9 J3 z
" I' ?9 ]! }" O c5 J
4 ]/ c# \) G: L% ~private:
" M- ]) q2 n# E; P% N& o6 b CUPnPImplWinServ& m_instance;
* b# [5 h7 ]/ j$ f5 L3 ]8 B LONG m_lRefCount;! H+ o4 B* Z9 J: m" L) P' s& y: y
};! ~: L* N6 E& H4 S$ G g, p& Y
* d- W$ i- q+ v! R4 Q/ K9 k' U N
5 K- C0 L! y' |( b+ l
// Service Callback
0 H! u. L6 x% n# Nclass CServiceCallback, P% R: z& l2 h
: public IUPnPServiceCallback
/ }+ @2 r+ k0 V- F2 ]{
2 }: U( x* Z% j* p# G/ x- cpublic:
6 j/ F9 @( M5 V CServiceCallback(CUPnPImplWinServ& instance)
/ f# A. R& o' h3 j : m_instance( instance )7 k- u& J, k3 q7 Q- F1 a$ k
{ m_lRefCount = 0; }% u) T& q2 u6 s7 w: Y2 V4 N
/ l) S) I( l" B- w' _
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
8 s7 T$ g% j! m9 H! F1 ^, f3 i STDMETHODIMP_(ULONG) AddRef();
+ b2 T' y% x2 Z STDMETHODIMP_(ULONG) Release();
5 F/ u8 p% r% X" T2 T4 D9 c6 r/ L4 ^; J8 Q5 J
0 G* ~/ P. |' z) d2 l( t% l
// implementation
" S4 g0 a6 |6 x4 p+ j" M% T# ~4 uprivate:
: e4 S6 s0 r2 |4 L: ^ HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);
O8 [( e" C& z HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);7 T( c% I% k! Y% s; a3 l$ y
1 b2 B ~5 r3 t
, [6 h) J; M+ Y; j& G/ A# l
private:, D8 h1 k* Y/ }" X2 L9 R( b( ?+ u- t
CUPnPImplWinServ& m_instance;
9 }; a# U6 W. T2 \* i LONG m_lRefCount;
: m" u7 W2 F9 [0 E};. g$ a& V2 m$ l/ j
( { l) g5 d, \
: o1 \, P6 `( I" k/ I1 n' h1 }5 z
/////////////////////////////////////////////////
+ J) f( O$ ?7 }1 y
4 j' n3 ^5 X9 B3 g( d }3 _/ x$ b) E
使用时只需要使用抽象类的接口。. Z! Q+ @+ W1 U1 s6 L1 `
CUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.
( s" i$ S8 Y4 e9 Z0 H2 gCUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.
; X. q! e% { p. OCUPnPImpl::StopAsyncFind停止设备查找.* j1 w1 C" E C
CUPnPImpl::DeletePorts删除端口映射. |
|