|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule,6 Q, M$ d5 q6 C7 F' T" n
3 N6 y3 U: Z" P0 f8 t- @5 y# d
- k' V) P" k3 r) n- }, V7 b& Q
///////////////////////////////////////////
% N6 n7 K3 h# P7 O//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.
?! O6 v# p' S6 A- u0 W/ q" `; E
) T+ G7 m5 h5 {#pragma once. Q8 f$ J2 h+ b& q
#include <exception>/ T% x5 Y3 W5 K s" t
& L0 B2 N( @- ?8 b- h- `) |) f- p$ `6 T" }; t
enum TRISTATE{* b/ c2 u' M+ T3 @7 X
TRIS_FALSE,1 t4 M" C/ w8 @5 ~* f% z4 I
TRIS_UNKNOWN,! ~5 D' h6 o! ]+ Y# c, U/ f
TRIS_TRUE+ v4 v* m2 r& o4 V* C) J0 L
};
4 Q+ C8 x7 ^- N) }# P7 W; @* P- q5 ? C6 k3 M, I
2 l5 q& ], Q0 h
enum UPNP_IMPLEMENTATION{
: P9 c: ?3 |2 m- m2 u UPNP_IMPL_WINDOWSERVICE = 0,5 S x) l4 R5 f
UPNP_IMPL_MINIUPNPLIB,
3 u/ \) e4 ]3 H; @, G UPNP_IMPL_NONE /*last*/8 W J% J, Z; @5 ?
};( _9 v" r1 K1 j% ^2 G0 d
1 b ]3 i: C2 [, Q
4 S* B6 e* l3 u* {) R
& A5 C1 R- J. V; H
- N" c# x! U5 Y/ }class CUPnPImpl0 F/ n9 z* V2 t0 W4 f
{
5 d+ P" E# A4 r; ppublic:
! A' Q9 S- ]9 z# {, q& D CUPnPImpl();& @" G9 f5 [) Y' k5 m9 t9 D
virtual ~CUPnPImpl();/ d0 j1 p9 b0 p5 E5 R
struct UPnPError : std::exception {};" x M% o! ^# I9 E3 ^7 S* Y2 `! h
enum {+ m, c) Q3 n& o7 k7 V0 d1 o) t: }' O
UPNP_OK,+ z- d! \& `. w
UPNP_FAILED,. y3 O0 _2 K: O) k' b8 x
UPNP_TIMEOUT
: i' M) D& N* J& s$ x; B };1 c3 Y9 j) l+ k% m8 Z
. [: a# J1 ?& w
( i3 z. x7 U, I# c8 ^8 \' | virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;
0 Y1 W1 S, v1 {* L7 ]2 X" m& ]! t virtual bool CheckAndRefresh() = 0;
9 d' W5 w/ \ ]9 q9 L. M virtual void StopAsyncFind() = 0;5 w" u0 m( }2 D
virtual void DeletePorts() = 0;" _) P5 F, H, v& q+ Y. e
virtual bool IsReady() = 0;. p6 G- G( q2 {) v# F7 }& A
virtual int GetImplementationID() = 0;
: N5 S5 x, c* k9 |" F9 E # e; C' K( |& V
void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping! k1 l- }4 g9 c7 E2 k7 p, T) J6 r2 Q
$ O* {' e4 J1 w0 V4 b$ o0 Z( n. |& `% M* J# s. q
void SetMessageOnResult(HWND hWindow, UINT nMessageID);. T% V+ Q5 P) @) w- S
TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }/ S" F" G3 G; n; w, j& p: a0 b/ e
uint16 GetUsedTCPPort() { return m_nTCPPort; }! Z( R5 G0 l/ d
uint16 GetUsedUDPPort() { return m_nUDPPort; }
8 @" A; ~) i5 q5 \; { H+ S2 R6 ]$ d/ q( ]; D X
, U. W0 ?: X' `+ b5 l* b" T6 R
// Implementation* A% ?9 w0 ? l" Y/ J
protected:
2 H# I0 C3 ?5 u L, G) h volatile TRISTATE m_bUPnPPortsForwarded;# |/ _6 U0 r7 }: t
void SendResultMessage();) Q4 Q/ d4 |9 @/ e) w
uint16 m_nUDPPort;& K9 M; ?7 m5 P4 O! Q) I
uint16 m_nTCPPort;- V3 }9 d& i6 E' f( E j/ k
uint16 m_nTCPWebPort;4 k5 v3 g( h/ ]% q$ A
bool m_bCheckAndRefresh;0 ?3 s; S# r t1 u) _
) V( t& F! i" o0 c9 X( p1 W9 ~) Y) p1 g0 h& D4 n. t' q
private:& P) h0 M% t2 ]7 u# W5 i4 D
HWND m_hResultMessageWindow;" k# C; U9 Q* a1 k
UINT m_nResultMessageID;6 t' l' l5 q/ N: Z, I& Q3 ]
7 W6 X6 `. x$ ]3 R0 g% \4 E
; Z" g7 T: v% v$ M$ T
};: G2 d+ s d$ M% Q8 A
7 E( t3 a5 k2 i9 }/ h" F( O3 x& y ^* e( T) U: B
// Dummy Implementation to be used when no other implementation is available% y: i1 y: t6 V R: H+ D* A
class CUPnPImplNone: public CUPnPImpl
( w5 f) V2 n) i{7 L8 ~$ e; b9 O* N8 j( D
public:/ z# h* _9 ]7 a5 k" H" M
virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }8 t7 u( s& ?+ |
virtual bool CheckAndRefresh() { return false; }8 ]/ [+ }; L9 t& u7 Z; A4 m
virtual void StopAsyncFind() { }0 |, C4 o9 k! \! E! b
virtual void DeletePorts() { }1 |8 G; e# C# r, }8 a; ]9 R
virtual bool IsReady() { return false; }
1 e3 ^/ z$ U+ |/ l$ ~- h+ b' Z) r virtual int GetImplementationID() { return UPNP_IMPL_NONE; }0 N* M+ G! `) y. }
};
4 W' @8 |6 }2 O- `" _! b( E9 K X; U$ Z* f q
) a, ?$ ~" Y; M8 B; C9 T3 u7 ]/////////////////////////////////////. P( ?+ H9 R) n$ q8 B- d' m
//下面是使用windows操作系统自带的UPNP功能的子类0 K1 Y# {! d9 o2 e
) E1 i- e% T' @- B8 i/ U1 O8 F
6 s0 D6 O) i+ X# w3 [, ^) f! ?$ B#pragma once
/ i* b# _: u* c. t#pragma warning( disable: 4355 )
+ r, B* H6 c: [% G- |2 ?9 y A$ ]8 f S5 u4 [( y
8 k4 Q" J: m( @#include "UPnPImpl.h"
8 p3 r/ _ z0 E* I0 w#include <upnp.h>
! z- M- J6 M5 c#include <iphlpapi.h>
6 F" @7 O4 }% J2 w% z0 G5 |7 o#include <comdef.h>
" e2 u4 }8 z, `' X9 C. L#include <winsvc.h>
7 e* j) A* v% M+ `1 c0 w) l B1 G
. r# ~: T& [8 ]% d#include <vector>, c9 i9 F& h0 u0 k$ p% }
#include <exception>5 x0 D, q1 ^7 i; z
#include <functional>
/ d W5 O( M6 ]: z* J) V' Q1 {/ H
. ]% p/ T6 D# A
h4 B/ ?# A v: q Y: M2 A, E* I* S+ x8 V( P# ]+ X1 M4 u
5 h8 {) o! W6 c6 Y$ O& X6 j5 D S
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;3 N% C+ K/ O0 {' D7 W1 D
typedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;( m8 i( p, S8 B; M: e( X
typedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;) o6 Z" j: H* k7 Q n. T
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;4 Q* z( ], k$ F! e
typedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback; V; U) G4 `, o5 G
typedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;7 e+ t! ` C0 x+ O7 M" {* D: S
typedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;
2 ~! X, }% Z' i
8 c5 j b9 |' e$ Z$ f
w' M' _* g; W+ y, ^; S! Ktypedef DWORD (WINAPI* TGetBestInterface) (% a7 s3 }! l* ]" f- |3 D* N u
IPAddr dwDestAddr,
5 h* |# b, M$ z1 y6 @& m) [ PDWORD pdwBestIfIndex
6 }: E; U5 @5 X# y* _/ e3 z);. q' H, Y6 f; s& B. b/ `) w
4 Q( ]2 Q% p5 I6 b/ ? m. [& F' b2 V: o. x8 `2 T* ^, Y
typedef DWORD (WINAPI* TGetIpAddrTable) (' ]+ ^* g9 H$ n9 e" `. C4 t
PMIB_IPADDRTABLE pIpAddrTable,
4 R8 Q7 i) F5 y PULONG pdwSize,4 Q# }! z7 R$ \4 H) }- Z
BOOL bOrder
2 g& U$ j) c% P2 U" z);+ k2 m: G; V5 r4 v8 T6 T/ V+ c
6 J$ T' [" E3 V5 s1 t, [
" H8 g9 U6 L1 X, c7 E3 M- m* ltypedef DWORD (WINAPI* TGetIfEntry) (2 s# { q7 g% h- t" k$ S G, X
PMIB_IFROW pIfRow
, I: u4 |2 K8 E2 R+ L);
' e3 }' S( L* V' @" C, F( x0 g
* p! E4 A6 h1 K5 ^% d4 o* }. t5 v- A; r& C; ]$ i( w
CString translateUPnPResult(HRESULT hr);
' d! j8 E5 O' v+ X7 d! dHRESULT UPnPMessage(HRESULT hr);
# x: i2 S) u; V7 j$ |
D9 l- r9 z! {( k. f, g
5 Z% @0 N; ]( J6 K9 Iclass CUPnPImplWinServ: public CUPnPImpl# {" A7 |% v5 c& C* e! Z
{( C$ A% [& _1 \ j) H+ J r- k
friend class CDeviceFinderCallback;
. C; g- a; R6 v5 L, h0 k! X friend class CServiceCallback;
, x8 `% y% R4 T4 b) N4 \" V// Construction
/ T, c7 S! G" o+ tpublic:1 q7 u1 P3 v4 N. F" j
virtual ~CUPnPImplWinServ();* w+ `# }7 H% n# U$ ]# u
CUPnPImplWinServ();- ~9 w: k3 m' I/ t L- J! s
e+ \# }' v8 |; a5 c
4 P, \$ _1 @; X5 ]7 z) h virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }" v2 s4 e& J0 u5 u$ L! r7 `
virtual void StopAsyncFind();
( S* c# P* w9 J7 H virtual void DeletePorts();# V) k) l( P( f
virtual bool IsReady();- q& x2 U( d) y
virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }
- s* s: K9 h% N1 r2 r& ]- [' y4 d9 V( x+ _
3 G$ [2 P+ d. S
// No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)1 [8 r4 V# U) s: S* G$ j9 L9 ?) O
// the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later
" V2 s- M# j3 ~0 E. a1 q4 e' Y virtual bool CheckAndRefresh() { return false; };
2 J4 S" K+ N% R
. I8 {1 l, e7 m4 u
/ D6 P3 B m4 y: tprotected:3 L4 G4 y6 }: J5 H6 l
void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);
+ l; H( p- z+ @0 g5 S void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);7 x' c" g; P2 r' @
void RemoveDevice(CComBSTR bsUDN);
4 U6 R. {' b) ~! o5 T8 \5 {( n bool OnSearchComplete();8 q1 C6 V- V2 `0 i
void Init();/ _+ h1 P: M' I6 Z: C0 N# O
, Z w+ P9 O8 Y. A% O2 \
, t/ r5 v! u: o% l: S
inline bool IsAsyncFindRunning() J1 Q5 p& x8 z% @6 _7 K
{
# E! b- V, v4 Q$ ^4 O1 o6 a if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )( N2 J$ v# T9 H% H8 c' D" S
{1 r, U( B- n W4 O { s4 g& E* w+ O
m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );' P8 a: m7 X& k, F
m_bAsyncFindRunning = false;$ s9 L& g0 z8 n: o% c6 P
}5 ?" t. E( g6 a4 p7 r6 I+ d6 h
MSG msg;) m5 ?1 B) N' G. a% ]4 Z: |/ {
while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
3 I! ]. e* x ?0 y; c' b# F! h {5 b: v2 u1 X+ F$ `
TranslateMessage( &msg );3 A$ _, \0 w3 N' a$ s* D
DispatchMessage( &msg );' R! J$ S4 E9 g/ ]" t3 L; S
}
; ^3 `8 N& ~- G return m_bAsyncFindRunning;) S& \, y0 P7 l0 q: z% l: R6 ^
}! V5 I9 _7 C7 E( w0 h1 {
! T. [4 n4 x% d0 {$ R$ {" S# x
. V# c- K2 e) }( i# h5 | TRISTATE m_bUPnPDeviceConnected;: g' ]; E& |( h) V; l) W
5 B3 g- c) s6 g" P5 q/ O/ L
6 b2 p( Y+ {/ u/ ^; R& T+ h0 P
// Implementation: N3 s8 y3 O1 ?% v
// API functions A* [( l& c2 s/ L2 Z7 H
SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);
( z( H* C+ Q1 E. I% Z SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);: p1 d6 E. @) d2 M# ?4 ^ }
BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);, `: J7 X9 h5 Z0 X5 t! m+ x
BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);
& o) o9 X# y# [( Y7 E; w5 M BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);
1 f/ N1 W. N) ~0 P7 ]+ T1 f BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);
/ g6 @8 ^4 c# {3 d5 I7 O
" {# k; U5 H6 ]$ F# ]/ |
% O9 J# Z) Y/ M5 x) f4 _ TGetBestInterface m_pfGetBestInterface;# I) L+ M9 j* ?. o% \! L
TGetIpAddrTable m_pfGetIpAddrTable;' k3 [2 s5 G5 a7 [" Y( H4 u. z
TGetIfEntry m_pfGetIfEntry;+ q3 r% I) p, Q6 j( a
/ ~0 F/ J/ U" w: `! J" p* q! d: @
" J+ z& Q4 N1 ~, A. C5 i m
static FinderPointer CreateFinderInstance();9 i7 y% T* x, M9 N
struct FindDevice : std::unary_function< DevicePointer, bool >8 ^$ P$ X5 t, F# U' t; Z# h( f
{
5 O/ x3 a0 c+ u$ x! y& [: D6 i- q FindDevice(const CComBSTR& udn) : m_udn( udn ) {}$ R. U! Z- f1 w4 V. ~
result_type operator()(argument_type device) const
! v0 b' x9 l; ~) z, T {
' n+ b6 ~ g2 @3 B4 C CComBSTR deviceName;' q( w. b# f% W* P/ L
HRESULT hr = device->get_UniqueDeviceName( &deviceName );
# _1 g4 p( D# K% W* o% o, G( `/ {! h* [
1 J2 ^/ _: q" E5 \6 w; h2 e
if ( FAILED( hr ) )8 W9 m8 F* X: L& X0 d
return UPnPMessage( hr ), false;( j) L0 @; z# u3 a6 p
+ Z, z& A! D5 T, \* Y
4 I+ d3 }8 }1 k* `* {4 O8 r return wcscmp( deviceName.m_str, m_udn ) == 0;
; U& V/ m h( p. Z, G' Q$ m% d }0 B( R/ V' [2 n7 F4 M! i v
CComBSTR m_udn;. }) B! Y7 N' v
};. D+ H7 e: U8 `$ E! b; d$ V: C) |
& B' `# k+ Z$ r0 E/ W3 z* P& i" V/ l- w; U
void ProcessAsyncFind(CComBSTR bsSearchType);
. |1 W4 ~# e! q8 @) q% I: J HRESULT GetDeviceServices(DevicePointer pDevice);
- V7 O, `+ g6 Q8 C/ s void StartPortMapping();' T$ x ^- i) S
HRESULT MapPort(const ServicePointer& service);* `/ v2 y1 c8 S1 X4 ~& [; _
void DeleteExistingPortMappings(ServicePointer pService);3 Z: p" b0 H9 |
void CreatePortMappings(ServicePointer pService);4 l2 _' }6 ~9 B' k
HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);; @4 N& M+ x, T* m
HRESULT InvokeAction(ServicePointer pService, CComBSTR action, : ^3 G7 j/ [# Z3 ^
LPCTSTR pszInArgString, CString& strResult);
! y4 W: h) r+ n: V1 u void StopUPnPService();
7 f! F$ v7 ?: {( a. i
, \9 L9 a7 K$ O0 r# j+ V/ U/ E6 n" s& G+ ?
// Utility functions
; L" g8 C: }! g/ r0 }' L/ f HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);
( }; m- g5 ?+ |# \9 c INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);
* r1 G7 L% b/ T5 w3 X INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);
& O9 S' i: S9 K" C) @ void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);/ I. p: U) I8 s) P1 J) X
HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);$ w7 m7 s+ u/ b% R5 i
HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);3 g" H# p; a( h
CString GetLocalRoutableIP(ServicePointer pService);
' _3 ]2 s. n+ n% V7 n$ p) l. E4 L; S R$ U
0 Q7 ^6 J) l. M& n7 R// Private members
! {, J5 B* G1 Y A8 `, i6 p! B. ]private:4 m8 E8 z( w3 X$ R! B$ a
DWORD m_tLastEvent; // When the last event was received?
' H. o- v$ {7 p. J, _ std::vector< DevicePointer > m_pDevices;
9 O+ q% {; i7 c std::vector< ServicePointer > m_pServices;3 j8 Y, Q8 z. I
FinderPointer m_pDeviceFinder;% G8 L g2 e. p2 j- ^
DeviceFinderCallback m_pDeviceFinderCallback;
% [; B' F, T' O5 g$ i ServiceCallback m_pServiceCallback;, y/ b& H" h' W
q( @5 f% a1 x5 Z7 I* t7 E+ o \0 C6 L8 L. z; F# b
LONG m_nAsyncFindHandle;
, [# L+ U, d3 U7 P$ U" u bool m_bCOM;
$ ^% Z1 a$ l3 }) V7 m bool m_bPortIsFree;
9 t: Q' e5 X0 D: r$ F7 v CString m_sLocalIP;
1 H1 e' l. T: b CString m_sExternalIP;: K/ x: j* f) ] o6 B7 }, ~
bool m_bADSL; // Is the device ADSL?+ C" R& Q, }1 C
bool m_ADSLFailed; // Did port mapping failed for the ADSL device?
3 k2 e$ T: }$ S0 H- d' o1 z bool m_bInited;
* K i4 w. p. G/ P' D, d- ^ bool m_bAsyncFindRunning;
4 o/ ^5 L9 ^( J0 ?7 Y7 [" X; M+ U HMODULE m_hADVAPI32_DLL;& S8 R3 x/ y- Y$ K6 o: t* p
HMODULE m_hIPHLPAPI_DLL;
9 h# x7 L" m4 O0 { bool m_bSecondTry;/ s7 m* t. h9 j" D! J
bool m_bServiceStartedByEmule;4 W2 t+ s8 @' k# B
bool m_bDisableWANIPSetup;6 {) b& ]6 a) u* B, G8 |- w* W
bool m_bDisableWANPPPSetup;5 r& P c; ]! F8 L
) u! `4 [% a% z/ H- q
* |" a2 Q, I: W0 P};
3 I1 s+ E; b" C/ ?, W9 ?. d6 z7 Q0 V! u* M# F
" h; V- k& n/ r- e- s1 o" m
// DeviceFinder Callback
9 F# ^+ S9 ]; S+ C3 ]class CDeviceFinderCallback `% x& R4 x( t5 `- T
: public IUPnPDeviceFinderCallback" v' \. J8 q! b! }7 N' |: H C6 l
{
) m! B* S/ U6 P8 Z3 \3 opublic:3 t: A# g: {0 O1 ~
CDeviceFinderCallback(CUPnPImplWinServ& instance)7 {5 A3 H$ O g$ G% Y/ q' Z7 q" ^$ e
: m_instance( instance )
5 N& j1 k, z" N# A" L: c c { m_lRefCount = 0; }' M1 ?& v# g7 k. }: T
; p5 ?" B2 Y9 l, Q$ ~
# k' B$ |% T" d: Q% }; i& p0 D% D$ V STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);, O1 W: ^) x3 u* O2 A6 Q2 M7 |
STDMETHODIMP_(ULONG) AddRef();* L" V8 B5 U$ I7 |2 y9 Y0 B# u
STDMETHODIMP_(ULONG) Release();
- y' J" n0 ?9 I& I- n" @
4 a$ f2 e# e* E; T: x+ g. R, I" k$ {( F. A# r6 i
// implementation
% d+ a! F- ]: e* W9 ^; uprivate:5 i) q" Y6 T8 t$ W8 J; B7 W
HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);
n2 I. L5 t# ]3 C5 K/ [; x& B2 Z HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);1 ~- }4 D( Z- a* D
HRESULT __stdcall SearchComplete(LONG nFindData);& X; y4 n$ k& X& P9 K3 e3 U
/ z; m' a& y. V9 j/ }) m
3 E9 {' A9 k3 t: y9 D) V$ P) Y9 F
private:
+ J1 n/ t! Z8 t) P+ m+ A CUPnPImplWinServ& m_instance;$ S* g" s' \7 V9 Q
LONG m_lRefCount;" p- V1 s) M8 ?/ B4 _- e
};$ ~$ Z" r X e' ]0 B8 a, w% d
3 ^9 C3 V* U; E9 _7 G
$ x' O9 |3 l: l6 }" _# T# W// Service Callback
0 ~0 a1 l0 `1 W0 Rclass CServiceCallback
+ ]0 \" w$ Y+ {& [ : public IUPnPServiceCallback
% O1 a+ R& K1 ^$ ^{; i7 f' L6 G' w1 s2 I8 R
public:( @# N1 J# R/ Y3 l3 ]
CServiceCallback(CUPnPImplWinServ& instance)! S; z9 ~0 |' f8 Q0 N) W1 n
: m_instance( instance )
0 T% F, D- w) `. H, Y { m_lRefCount = 0; }1 W! P. j( }% c7 h
8 I) j1 x* t. h9 U" {3 m STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
+ f1 `+ D. B$ h STDMETHODIMP_(ULONG) AddRef();$ g8 o) ^! @0 e: w8 g
STDMETHODIMP_(ULONG) Release();
! o4 c; ~7 D/ w8 L$ U6 v) C; c* Y: g3 J4 p# H* D& [
) P5 U) A- I& W! x; M$ ^9 W9 j; q
// implementation
7 v4 k; G; M2 M! B) p. Vprivate:7 y% n7 L6 Y1 P
HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);
8 J2 S7 }. L& M' ^4 n+ h" n( M HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);
b4 C5 G" Z& I# V+ ~, J8 _7 `. q* u4 X! d
; b7 J- i7 Z/ ?+ [7 b [2 Q/ Wprivate:
+ \ M( w" V$ {! x6 R, Y( c CUPnPImplWinServ& m_instance;$ Y" z# ]4 y8 d/ ~1 _- Q
LONG m_lRefCount;/ {9 q% e3 a' W1 G2 x
};
) a, R1 M- Q- k8 z1 O
* I9 c, {9 x" i2 x. [4 d; v2 |( J2 }$ x
/////////////////////////////////////////////////
- y' Z- c1 R6 J( A* Q" h- R6 J# q
8 Z" L( P) ^" c: x
使用时只需要使用抽象类的接口。* M" a8 R& ~: } p
CUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.: R3 l) i+ S' Q9 i( L- A* x* c
CUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.3 o- t! Z7 ^. q/ \
CUPnPImpl::StopAsyncFind停止设备查找.+ Q9 |) H1 A$ H9 F2 n, E& f
CUPnPImpl::DeletePorts删除端口映射. |
|