|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule,- m( L' O) B3 |3 a$ s l$ h4 S7 H
# v% ^' ?1 D& w
% @" i% F+ b3 `: J///////////////////////////////////////////3 G3 {. X) m) A0 A. E
//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.
" r: E3 s+ k% ?' k6 }& U4 J- J4 s& n' @0 o
- u2 A3 x: @8 f( |( _, N5 e$ ~: ]
#pragma once7 I7 A: P' w9 A- }
#include <exception>
; W+ e) w/ L$ P- J" Z' z
+ D C5 t; d% F7 C S! G t* r1 v) I2 W2 x, f
enum TRISTATE{5 s8 y8 o: a7 Y. d4 I) u
TRIS_FALSE,2 U+ P7 R7 P* Z( v- p: w! ~
TRIS_UNKNOWN,
% F2 O5 U" k4 ?; x. ^9 t6 L o+ N TRIS_TRUE4 p: w, z: _3 g' J* ^4 ?
};
& n# X1 p O, y7 p& f) s8 `& A! I" z1 z/ \
. P0 M& G* K( }1 G5 f8 P; v! w5 o/ ]9 @
enum UPNP_IMPLEMENTATION{
$ S8 `+ f* v$ f5 S UPNP_IMPL_WINDOWSERVICE = 0,) F! X! M3 S0 d: I- J
UPNP_IMPL_MINIUPNPLIB,
L6 k/ T8 P9 z: q UPNP_IMPL_NONE /*last*/
/ O/ j1 R; ^, q, ~ Z};4 w9 m- _8 `" L6 X$ q+ T
2 d! _1 F: b) w7 g
3 I5 s7 \* i- Z7 e1 a+ C! t& ^& F) {0 z
- y, p3 m3 T- n$ ?
class CUPnPImpl8 d+ p( h. I$ I1 f% i- q5 F
{5 q4 [# E/ j6 g R6 W# n
public:2 x' z6 q E5 ]( K/ l( K. h
CUPnPImpl();
5 u8 ?8 L. [0 ] virtual ~CUPnPImpl(); ^) q7 j1 k+ i5 o# Z
struct UPnPError : std::exception {};
! [! y u f" q enum {
: Z. h. J+ Q, B$ r+ _2 D4 z8 {$ k UPNP_OK,) C- O4 u& j. S4 Q" d
UPNP_FAILED,
* }# N9 V7 O( S7 q/ t UPNP_TIMEOUT5 C8 W5 j4 F, |: b
};5 t1 q) X+ B7 j2 T
e+ ^8 d- F3 s2 T4 a
" I- _$ ^" D2 d3 A' A
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;
9 K8 ~, y# x9 n* l7 [: X9 l virtual bool CheckAndRefresh() = 0;
9 `4 ^2 N/ t) y9 c5 ]$ {5 N virtual void StopAsyncFind() = 0;7 w) G& G3 S% ?5 }# T; A
virtual void DeletePorts() = 0;0 X0 w% g$ R; U q$ h( w8 I) J
virtual bool IsReady() = 0;
$ d8 R+ [ v& X" m8 ~ T$ P- m9 T% l# C virtual int GetImplementationID() = 0;6 C2 H x. N j
% x+ E1 d& i/ ~$ B+ R7 B4 q9 j void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping
) c+ B' N- B" {, i( D/ X) ?2 ^- P K9 X# k/ }$ g
0 k+ Q3 r7 j* X2 J7 x void SetMessageOnResult(HWND hWindow, UINT nMessageID);3 i; Y4 s' {# k/ s- F! A* W0 P) i
TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }$ U! e7 D& { V7 {6 o
uint16 GetUsedTCPPort() { return m_nTCPPort; }$ q% u) W( z6 J7 P) @
uint16 GetUsedUDPPort() { return m_nUDPPort; }
3 P* x. H3 [" S; _- W7 q2 k
4 @3 Q: L* ^9 V) g
; d" M1 p! A1 F# [ G' V" @// Implementation
* C$ s8 Y+ K6 T( z9 o/ Iprotected:& ?- G( f1 [/ p6 c1 W
volatile TRISTATE m_bUPnPPortsForwarded;4 x7 D6 B6 q u: I# X, Y$ y: F
void SendResultMessage();
+ _" y- C& d9 [) {6 H# l8 a" h uint16 m_nUDPPort;& G2 g+ W: y# F7 F, q, Q+ f
uint16 m_nTCPPort;
# N+ [& w- G3 z6 k$ ~6 q# P1 x5 u" h% ` uint16 m_nTCPWebPort;
$ g, R) ~% I! X+ K6 B9 j bool m_bCheckAndRefresh;
# n8 j2 M& T. {
- ^2 V! H8 p, W7 U" A
' L+ k4 H! S/ y5 S0 t/ Pprivate:/ i5 J4 m: M; [
HWND m_hResultMessageWindow;
8 P8 R1 c0 @) g& Y0 A# k' h UINT m_nResultMessageID;
6 u, c C3 _1 i% w
1 `# R0 n+ Y- `/ c1 L: u" g
9 S$ P _3 c, A! P};: w! P2 j% S" a: ^" w
7 m+ X7 E) e# h* F
) d( J* M5 R# }" Y& o$ s// Dummy Implementation to be used when no other implementation is available
4 L. _7 F1 n* q1 a- x- Uclass CUPnPImplNone: public CUPnPImpl! V) V% Z% M' t) Q, u
{9 L' u2 G* s, c# d! [
public:; P& Z6 E) N3 o8 a8 i- E @ m) H* m
virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }
( S) s+ j( ~" n* R4 w3 U4 _ virtual bool CheckAndRefresh() { return false; }5 z/ ~3 ~. f: Q0 T9 L% D
virtual void StopAsyncFind() { }+ O$ V0 A- }/ u
virtual void DeletePorts() { }
8 U* | u9 S: s6 P virtual bool IsReady() { return false; }
3 e& A# B. X; y5 V' z virtual int GetImplementationID() { return UPNP_IMPL_NONE; }1 C8 z$ {" y; ]1 S- o9 J, a
};
0 S8 W* [* } m# x/ f) C/ P! q, h9 m ^- {5 U6 X5 O* w- \# n5 }
. |( o4 e4 M4 W. _( ^/////////////////////////////////////
( ]7 u5 {+ z5 U" B//下面是使用windows操作系统自带的UPNP功能的子类$ ~& ~! R( i" o' q; z. y
8 N/ Q/ a- H7 ^6 C, [
* C# Q& `+ m9 i8 e$ V3 f#pragma once
, v2 o0 S1 t6 v#pragma warning( disable: 4355 )
6 l) s) Q% {9 L" j3 J& L, k+ a' D7 k% @$ F' M
5 d8 e' }& B) O2 S$ Y, H+ f8 V$ h
#include "UPnPImpl.h"
6 A& ^2 D6 `, S; `6 `# ^#include <upnp.h>
$ e! E6 H7 p! T2 ~2 d) Y; V' \#include <iphlpapi.h>
% q* @% M. n- r- i: x1 N8 u#include <comdef.h>
2 g+ A! A( Z6 U9 \#include <winsvc.h>: C$ ~6 I( w0 c7 F
+ ^( G$ x; G" o
% a- {/ ^" q3 c9 D; z
#include <vector>
p7 L" c" J5 S! J6 d#include <exception>$ J' q' A7 c8 S! P* j5 u
#include <functional>! a& X# p; q5 d# |% a
4 |7 q. T% M A4 O1 g7 d( \' C5 y* d2 s, ~ h
) Q2 \9 O- z/ _' k5 p M/ k
& [, i! h3 a- E8 ?2 [5 ^6 [: W$ Wtypedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;2 i- \3 a9 k" Q& @! L
typedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;% f# V( V" ~: k* w# f+ q. _: J6 r
typedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;+ i# l5 f" ]; R3 }6 ^
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;
' e; X$ i5 m. [4 Otypedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;6 b8 O( a3 i6 V/ C
typedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;
! _! c }" f1 K" w) Qtypedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;
; E3 g$ i+ r+ V- v0 }) i9 c* D$ ^6 Q! p" {
1 y3 u8 `& I k; ^* }
typedef DWORD (WINAPI* TGetBestInterface) () l0 r7 V& \. P
IPAddr dwDestAddr,' P1 c! B: Q/ \# g* s
PDWORD pdwBestIfIndex
6 E* P) ]0 ]7 |. n a);0 `% h3 [- h& F9 X8 w% G
) f1 I( {6 _2 I% l0 B' k- d1 u) `5 k8 o) ~( d+ e
typedef DWORD (WINAPI* TGetIpAddrTable) (; a! R. ^# u( k I: |. x
PMIB_IPADDRTABLE pIpAddrTable,
: r, m2 G8 s; r1 r6 K PULONG pdwSize,. `/ v% i0 B, P$ O
BOOL bOrder
4 |( ?+ G0 O3 R$ ^8 \& v, g);
! I, Z C m1 `. o2 n6 M. m5 t" R- i8 r" A0 u8 h$ K- N
# ~: b: N( Q" q' d9 `typedef DWORD (WINAPI* TGetIfEntry) (
6 @: j% f4 l5 X& H PMIB_IFROW pIfRow
" X1 e" j4 z$ V% C" e" ?! F); i9 ^9 v6 {$ ]) d1 u5 L$ a" Q0 b
0 w5 J9 ~8 k6 K+ ]6 j# Q# q1 p8 Y2 }
CString translateUPnPResult(HRESULT hr);7 f" }" r7 Z8 \& M' z3 @2 p* ~
HRESULT UPnPMessage(HRESULT hr);
( |* r3 |# Q2 @, u& {4 p1 p
4 J! s1 u# U7 u3 z! s5 [ I: X3 U: S3 N; Y
class CUPnPImplWinServ: public CUPnPImpl
* x# Y$ Z, n+ c' @% R) x0 V( e{
* r7 ~3 ]! D- P1 n friend class CDeviceFinderCallback;, ~: R! Z/ |) I: ` h# q8 |
friend class CServiceCallback;
! }5 `5 u5 ^0 D8 U- G: V// Construction
/ C% N/ L% X7 \+ ^" i- o5 B4 Z8 `public:
" p+ R* K9 Y1 M( R virtual ~CUPnPImplWinServ();
! U* j6 ]1 u, C2 A" I5 D CUPnPImplWinServ();* G" g4 s# S7 [, e; ~* f
/ g/ M) ?& {* ^/ \2 A. Q( w, B* v3 N2 j
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }& A1 M$ m0 }9 C
virtual void StopAsyncFind();
$ L% \3 s4 i4 x E: O' \! s virtual void DeletePorts();) p4 |6 W5 c- ^$ l
virtual bool IsReady();
+ [1 k1 w; a/ @. {/ |" v; H6 K virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }
: b1 t( Y+ K: R, t8 B, I6 ?
& F. W" a% Q7 Y$ W+ b' p
# n V% K# k: m8 a // No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc). l5 r) }: j+ h9 ^+ s9 e) W
// the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later
K" N: d; n2 r virtual bool CheckAndRefresh() { return false; };
6 K/ ?5 I: T- v! e: T: N$ \+ h! R7 Q4 w4 N6 T
( ]2 G t6 [" B2 ^$ P6 M4 T; J) E0 E- g
protected:9 d1 n, {5 M; o5 L
void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);: O* d# Q0 Z) w$ ^0 z
void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);
+ I1 T* \9 H5 Z! @6 b void RemoveDevice(CComBSTR bsUDN); Q7 [# K2 z. j
bool OnSearchComplete();
8 t& c) [) w& l, d/ `& O; w& { void Init();6 E* `( h! q" D0 G2 W
- u0 c- m. q4 _# F# V% _$ k, s- K7 A
inline bool IsAsyncFindRunning() / c+ h6 h8 M( H+ m8 u. ]; W/ d. m0 A
{
# U6 S$ b' _/ o c0 W' s4 J if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )
. @: h7 M0 u' l {
: p' B. M0 l( n1 u% d. e. `. ] m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );
9 V. ]$ S; [/ ] m_bAsyncFindRunning = false;
# T! Q8 b0 a' ]$ e8 w }+ K5 R3 V" u! L+ k, W0 w# L$ O7 l. ], U
MSG msg;* w' q) n; I) R: C
while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )9 ^. c2 ^; X) Z4 P8 B A
{
! w) O+ W* {; l6 f1 k; l1 j TranslateMessage( &msg );+ C! w8 x/ `- ?7 P' }
DispatchMessage( &msg );
7 n; h) y- j1 U' c3 v+ q }. V! A4 m! _; Q6 j7 d" F
return m_bAsyncFindRunning;
% l$ H+ u+ G: { }
* ?4 r' X* a3 U& f8 z, Z8 _. a& F- a7 x! w0 A9 |' E
~& e2 u/ V- m) V6 Q4 F' }4 s TRISTATE m_bUPnPDeviceConnected;& m8 d- d: ~, Y0 S0 [% u
6 k+ m& N `1 N3 V: y, n9 w
3 x. k$ Q' T6 s: I8 J4 r) m" l( Z+ j// Implementation
1 G: g: m# o s/ ^% X2 J // API functions
/ H+ o7 V0 d3 q SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);
/ D7 M+ u" P8 ]4 i/ m- _ SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);8 P+ G8 ]; Q3 f
BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);$ _9 C* }4 @2 Q. \% f% h5 n
BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);* k' Y4 f) B2 W& o8 [
BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);
1 G& S3 y: z" U, N7 l2 N BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);# _. _# v* C. Q' c
# m* W1 T5 B& u* V
! G) K5 r' e. I TGetBestInterface m_pfGetBestInterface;# M/ L" _' y5 t
TGetIpAddrTable m_pfGetIpAddrTable;& b" P E/ F* [1 O* A
TGetIfEntry m_pfGetIfEntry;' `3 c" w; @8 X/ a" z
* \) a! V5 W3 S
7 p9 s1 s0 k: m) J4 B) w static FinderPointer CreateFinderInstance();
' i- u8 B% z* z" D struct FindDevice : std::unary_function< DevicePointer, bool >+ ]" v& f$ g, `: U
{
2 ~6 @6 C6 V! }2 e! P! e6 X0 X FindDevice(const CComBSTR& udn) : m_udn( udn ) {}
9 N) I. ^! z2 p& E6 w result_type operator()(argument_type device) const
) B$ f2 w* f# O2 ?4 z) B8 X- F {
4 e5 [! D. J# \# `1 c CComBSTR deviceName;; I3 E, K7 G1 Z1 g
HRESULT hr = device->get_UniqueDeviceName( &deviceName );' f4 d$ v; e6 a% r% f/ U( A& r: {
) l- K# d3 z& Y: X- W1 p
2 Z, E3 Q5 W$ N0 @. `" h1 S if ( FAILED( hr ) )7 S; K4 f6 U( Q$ t7 r
return UPnPMessage( hr ), false;
1 o" ~0 s6 y- v7 q2 w2 J
2 F+ O! X) `6 ^% ?! q: ~! m: U x' \) U: h/ C5 K g1 q7 `+ i. `
return wcscmp( deviceName.m_str, m_udn ) == 0;8 D4 p- G1 j, B% u( Z
}
7 h, |' v! m$ l5 t, j0 h6 ^1 k CComBSTR m_udn;1 ~. v s8 {9 e) U! A$ I- s% w
};
& Z+ l, a8 M: y $ ^$ X' l+ Y, c6 w4 ]4 U1 O4 V
void ProcessAsyncFind(CComBSTR bsSearchType);7 O6 b0 @6 ]$ d, `" e' M
HRESULT GetDeviceServices(DevicePointer pDevice);
$ ^ ?3 {6 B4 Z! p void StartPortMapping();* y7 R9 @6 W( E4 w. _% y {# N7 K
HRESULT MapPort(const ServicePointer& service);
8 x/ j% r3 o, x8 A3 ? void DeleteExistingPortMappings(ServicePointer pService);
" V, }4 D2 l7 i- W, N void CreatePortMappings(ServicePointer pService);
( b$ y( i! j( h% T4 n HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);8 r- a: H3 Q0 i7 r/ P; W: a
HRESULT InvokeAction(ServicePointer pService, CComBSTR action,
3 @1 n% _: a) K+ q LPCTSTR pszInArgString, CString& strResult);
$ T; H6 W$ t% }' |& v5 C void StopUPnPService();
, h% j G2 _$ G/ W* G! S4 z( \$ b
" d% O' Z& N4 {
// Utility functions% F: w4 f8 w& |
HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);3 k0 E5 ]; _; w7 L: l- @* m% p
INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);
( Q! i; K4 @9 l2 S8 S2 V INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);2 l5 c$ O n! [7 ]% t4 u& N
void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);' @+ e B1 H- D+ Q9 a7 e/ N/ M
HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);
I/ O- d: f% A HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);
& H5 I2 Q& U$ c8 X CString GetLocalRoutableIP(ServicePointer pService);
3 L, E3 l8 n1 y |
% o2 |4 R5 _' H) l% @$ Y3 @6 Y3 R% Z5 E5 h
// Private members3 Z7 v3 Y2 N' G8 C" A' L3 }6 j) W
private: a1 j* b5 H% K" V2 F* Q
DWORD m_tLastEvent; // When the last event was received?
$ R" w% E8 L+ z, d( d std::vector< DevicePointer > m_pDevices;. z5 u/ H5 W0 ~4 D- q
std::vector< ServicePointer > m_pServices;
3 U5 H. z" n+ M- Y& ]' b5 U FinderPointer m_pDeviceFinder;( o( Y% i2 V5 L, q
DeviceFinderCallback m_pDeviceFinderCallback;1 r+ z: ^" Y- M- H, o3 d! k) d
ServiceCallback m_pServiceCallback;
* S8 J* x- y% t& B$ g" a8 s2 @( _
! A0 o3 ?( w3 b5 E x* l4 R9 X) _4 t3 Z$ v u2 R
LONG m_nAsyncFindHandle;# y& T. `* W/ C, D) H8 I5 _
bool m_bCOM;, ]" H+ y! ^! P; G* g
bool m_bPortIsFree;4 h; `& d5 G$ D0 ]. L% s; G: f, p! \
CString m_sLocalIP;& b; N0 m, d; x* p8 h
CString m_sExternalIP;
E) q# B& y) o+ v) _2 k4 r+ W bool m_bADSL; // Is the device ADSL?0 A* s+ o; V2 }' y+ b
bool m_ADSLFailed; // Did port mapping failed for the ADSL device?
4 ^, x' C2 K& U5 ~2 C3 @2 |5 Y bool m_bInited;
8 L6 ?8 D3 b9 {1 B6 O# n# o bool m_bAsyncFindRunning;
5 o9 t. [) o2 g HMODULE m_hADVAPI32_DLL;
8 @7 W; v/ Q7 o HMODULE m_hIPHLPAPI_DLL;; D ~$ Z3 Q/ |. e3 S
bool m_bSecondTry;9 y1 M" k9 l+ N. o9 b! t
bool m_bServiceStartedByEmule;; n" T( H) j& ?6 K$ U5 g4 h
bool m_bDisableWANIPSetup;
7 k8 Q% @* m+ {7 P' c# Q bool m_bDisableWANPPPSetup;
0 _0 x5 @6 f4 ?9 o! \5 D( V9 e4 n8 s
. B- B; C1 Y. Z% y};
8 u1 R2 C$ c& p1 \5 R# q3 U ]* j4 f. f2 e7 n7 C
) D7 w; Z6 C& P9 I" y: H8 }
// DeviceFinder Callback
7 [, y, r5 v: Qclass CDeviceFinderCallback
# ?" S$ {7 m3 N : public IUPnPDeviceFinderCallback
7 _6 W% k& p/ c1 {{( L `+ O$ q- W, a& U2 R9 H
public:
- ]+ v3 U; C! \0 Y2 d w5 `" c CDeviceFinderCallback(CUPnPImplWinServ& instance)$ R, G4 \! i' F) Q$ w# W
: m_instance( instance )& |2 t: x4 O) k' ^; Z
{ m_lRefCount = 0; }
, |. z2 i3 L7 h0 c P& B1 j' o2 ]
1 f) A. q) ~! F1 [+ c# m- ?7 J6 ?. k! p$ t) N6 |! i; {; s4 A4 E
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);7 @" o' @ d. c( n5 T) k: ^
STDMETHODIMP_(ULONG) AddRef();' i+ ]' x- o& y0 U
STDMETHODIMP_(ULONG) Release();
4 g4 e% V# M8 { ?6 w+ o; H/ S* x; s' z; M% ^& ~* E
* L0 ]' T8 h+ D: {3 ~# d// implementation" `) v: ?. F4 G: y/ N3 Z
private:
1 b& w1 y4 |6 u3 p& y) ]+ ~ HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);
, v. m3 d S- ~3 T HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);6 m: @4 Z6 Z) @/ i
HRESULT __stdcall SearchComplete(LONG nFindData);
) {# w! y, I* p. ]- b. h2 U" w
0 l! f# _3 A% Y" u
) L: {: t6 I6 B9 cprivate:
" c5 G* K+ v, X CUPnPImplWinServ& m_instance;' M( n' w# w' x/ }* c+ H) i% I
LONG m_lRefCount;3 W1 C0 t& I4 X) T% k+ x% D% K
};
' h. I* e0 _' v7 S: e3 v1 I4 }! r* A4 q3 o
7 f/ o+ _' [7 n8 `$ @) u9 U$ U// Service Callback
% h( \; l/ R6 d$ W9 @' ^ Yclass CServiceCallback% H3 d0 q6 F: W9 g; {3 l4 u& d
: public IUPnPServiceCallback
" d4 b# x9 }0 u) J5 l4 t{: Z# z: y ?1 O* p, ?
public:
/ ~& C2 m; h/ j1 @. l CServiceCallback(CUPnPImplWinServ& instance)
3 M: Y. u7 D- k1 C# ^3 O : m_instance( instance )
; j: B. z- X& Y& z { m_lRefCount = 0; }, q: O! H8 c$ r1 v& P
; t6 e5 u/ A9 t3 o6 l0 W STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
: Y j+ T8 `" F: J, x$ h STDMETHODIMP_(ULONG) AddRef();
$ `- x6 _3 S( w5 [1 Y: q STDMETHODIMP_(ULONG) Release();6 }. E0 ?0 X) X) T4 l& r
; j n% u& _' r e3 k
9 V( t6 F6 W) M5 q( F" x
// implementation
5 j. l$ H2 ^8 w8 @4 _private:
" @9 `7 {- ?0 C8 D1 l6 X4 F; d' i9 n HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);
: S. g$ i5 x3 n# c+ _, x HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);) Z7 I, M6 c7 a& w6 t% ~8 [1 S
4 y$ ~$ V$ _ m' u3 Z& ~/ W- a" i R
private:
3 j6 j1 ` }* S P2 e7 d CUPnPImplWinServ& m_instance; ^* M/ v. E' g1 W3 Y h
LONG m_lRefCount;
4 x. K6 ~2 s/ f3 }& E5 ^};
- V" [9 w/ i- B+ x9 I
- h9 R& e+ N6 H+ M! D1 T( m( L1 z+ U1 n( w2 @
/////////////////////////////////////////////////
: M7 ^& v+ }7 R/ t* O/ y* t$ R& C3 N! a& Q# T! @
B4 t: r5 H4 M. w使用时只需要使用抽象类的接口。, ~/ N5 |* _1 j. M8 ^0 s
CUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.1 V0 ~* w5 T" L( W5 E5 P- o1 V
CUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.0 L- p7 z+ h( ~/ j9 e, ^# r$ ^
CUPnPImpl::StopAsyncFind停止设备查找.
7 b2 d' a6 B' N/ {1 d; C. nCUPnPImpl::DeletePorts删除端口映射. |
|