|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule,5 K- F. A }' a! c" O3 a& b5 X
2 U. ]7 t" s3 b
/ r, L+ z7 W. R$ G" y" b///////////////////////////////////////////( G8 v' N% B) f( ]
//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.
4 {6 u, o/ b7 i1 i0 m3 |& i. `7 |
5 w- x; v7 @+ u7 T+ T% J. t4 N" |& h' {2 `" y. x1 N# J
#pragma once% w2 v# X+ @9 O; Z( n1 ?
#include <exception>
2 w4 w* j8 j! Y' E2 F7 e4 l& s7 M6 \ v5 K
: ^* v" P$ k9 Z! c7 k9 o+ `' { enum TRISTATE{
1 ^; ~: H6 m: N" v TRIS_FALSE,
7 F8 u, f- j& p' V' R& N5 G& N$ Q j# z TRIS_UNKNOWN,8 _0 K' t' U* ~9 q, X
TRIS_TRUE
9 h/ ]3 ~, G5 \# B7 J# Z/ B( H! Z0 x}; p( @* W4 @, _
' T, l8 r9 j. h$ x
) c' M; o. m: {# v/ V' venum UPNP_IMPLEMENTATION{: t ^. Y4 o/ E; d( f
UPNP_IMPL_WINDOWSERVICE = 0,
9 f& I) u6 p, H1 ^ UPNP_IMPL_MINIUPNPLIB,
. p* ~+ Q( G6 N UPNP_IMPL_NONE /*last*/
2 D9 b% i) h# V- g% `' w0 u};
6 g) x5 M4 P6 _8 }0 u
! I4 R0 t1 J+ G% R2 B" Y
9 T# U j' D4 ^; r- n( k; U& _0 e5 ^0 f7 r+ U, ?" W* [8 @
# \2 e+ R4 W* h9 n
class CUPnPImpl- A1 A' K P9 j6 ~8 X+ _# ^ P
{; M6 P- i2 y2 p l1 j( u/ y
public: Y5 S4 G( f, j& ~' u
CUPnPImpl();, ?# K# k5 a8 O, r3 N; D Z
virtual ~CUPnPImpl();
) Q1 B& R# Q7 B4 a7 i! w& W6 X struct UPnPError : std::exception {};
) h' l8 |7 b0 v% ] enum {
, E( r6 L" W: y& L UPNP_OK,2 W3 }6 z, s$ r6 s
UPNP_FAILED,
: F9 U8 `' A! ~8 b9 L+ R. \ UPNP_TIMEOUT
% }! n+ T) E* V4 d0 l };" Q% K" G- _% Z/ K
9 q$ I) K5 @5 o; `8 C5 x3 q) D8 w$ g' |% P0 D) u ]
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;
, i# v$ B1 v/ D virtual bool CheckAndRefresh() = 0;1 c1 s) Z" e- @ k& l! S; y, `3 C% @& C
virtual void StopAsyncFind() = 0;
6 A9 O' X% h- `% ]9 g2 Z* Q6 @ virtual void DeletePorts() = 0;* {( g* R R1 z* L
virtual bool IsReady() = 0;
9 K3 x% G1 ~. M* S* f virtual int GetImplementationID() = 0;8 N7 Z S. c& Y7 e
& h+ Y9 H, r0 q void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping( a$ l# [' k- `0 ]0 P# e% g4 L- G; J
) e: I A5 ?4 ~6 N+ c
& N! y, X1 N& G! i# i' c void SetMessageOnResult(HWND hWindow, UINT nMessageID);* S6 @5 G& f0 O/ B9 `; d& u, Y( @- y
TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }
) B6 _$ A5 C5 Z9 ] uint16 GetUsedTCPPort() { return m_nTCPPort; }$ t# R `6 i4 o8 x- n
uint16 GetUsedUDPPort() { return m_nUDPPort; }
/ W" }$ u- g3 D3 R+ X5 P; d# u) i
# K9 k2 o7 g3 q" |
6 F+ A; ~: h0 J8 S3 D// Implementation
. P' w& g! I9 fprotected:6 i/ G+ |) N6 q2 W5 T
volatile TRISTATE m_bUPnPPortsForwarded;- W6 n; K- S" {9 k
void SendResultMessage();9 g) p' m$ G' P0 l3 X( F+ x. T2 s
uint16 m_nUDPPort;5 O# t/ E; S P- k0 x
uint16 m_nTCPPort;6 T- @+ Y( c( b
uint16 m_nTCPWebPort;5 W- `# X5 a _9 ~8 ?
bool m_bCheckAndRefresh;
3 w s: ]* F. Q8 `) E# Z+ p- U1 s6 L! c9 V/ w4 S! x! |& J# R' \
. W6 Y$ U7 d: m% q) |, e
private:
! C) }1 h: ^; `2 {" V( A HWND m_hResultMessageWindow;
" m4 D: C- v4 p8 H UINT m_nResultMessageID;
L" g0 O& o$ ?; V7 s8 n* ^0 {5 h. A8 c6 O$ Q O1 t3 Y# [
& \4 C8 Y/ [; w3 O
};( ?6 A& J+ V: _: z4 R# r0 j
3 x d1 o/ ?7 r: Y$ W
: M! Z- R' O" ~9 I0 M// Dummy Implementation to be used when no other implementation is available" w4 Q# |! D& z" U; d
class CUPnPImplNone: public CUPnPImpl
0 \ o$ C) y4 ~{
/ L1 \ W* Q' q& ?public:8 r4 E+ V) B8 {+ |3 k" { E7 Y
virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); } Y) Z* M& M- r- g% R
virtual bool CheckAndRefresh() { return false; }
6 w" A% V* z% d& _2 t5 ` virtual void StopAsyncFind() { }
$ E1 f- L1 p2 a9 V virtual void DeletePorts() { }9 ]! C1 W( S0 S4 B4 u# p
virtual bool IsReady() { return false; }
& g* T# g; g. z virtual int GetImplementationID() { return UPNP_IMPL_NONE; }
3 R) _5 v1 f& _/ C& I% ?};
2 h. `. m2 H5 X0 b# V6 S% x, f5 Y$ i8 h
" ^; o" n7 @0 C9 D
/////////////////////////////////////8 q5 ?6 w! {3 Z' I9 y+ @$ d; B" ?
//下面是使用windows操作系统自带的UPNP功能的子类
. `6 k& V5 u6 T! I- R) h0 |$ _6 u/ k; j7 b1 ]/ h
. k, i: K& R: Q( {0 O% r5 ?
#pragma once8 d* F7 W! b* S' q: v
#pragma warning( disable: 4355 ), ]& R- o9 \* K+ ]8 D9 t! Q
+ k5 S; O$ ?) C5 G7 E, w$ Z6 o6 S& ]" m- F
#include "UPnPImpl.h"
4 T5 [% I* F3 ^# W2 k#include <upnp.h>
# T' }( _0 r, r# E- F#include <iphlpapi.h># M. D/ f+ V- B* J- G$ Q2 C: S0 y
#include <comdef.h>6 ~) w( d/ i" O; `" L/ P
#include <winsvc.h>
! e/ W# h! X9 L) B) Z0 |. V/ h1 P# J& l! j: E3 e
+ ^$ y, J( Q) }8 e#include <vector>. V; s% y, |' t) x
#include <exception>
% T7 o! j' J9 J' }#include <functional>$ k H$ }" E; b. S4 Y% K
: h' n; p+ M, M7 m% m
: {. H1 C7 u6 `5 R
6 O" L3 W Q, _" [( |( O
9 k+ H5 j2 Z8 E3 vtypedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;
0 o: C. J/ x% G% \2 `: l, Otypedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;" K0 G9 Z& ^& P
typedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;5 p6 G$ ]6 c# e+ Z; o6 n
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;( q( T; k0 J8 {2 K6 r
typedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;
$ G( A- T- ?6 Y y& V$ Q' |$ ytypedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;9 ]% |& J8 _6 Z0 b
typedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;" u: }2 a& t5 ?/ t |3 D: Q
" U8 y G0 Z' z1 W
& N# E* n5 {- m i U7 Ytypedef DWORD (WINAPI* TGetBestInterface) (, r& @% A: O/ ~& U! p
IPAddr dwDestAddr,
" Z1 M: d1 g; G) \# Q' A7 r PDWORD pdwBestIfIndex' u+ O" w2 ?, s3 f' w
);/ L4 q1 G l; I" M+ Q3 {! w& e
* ]9 u' u% k# U* o7 W
6 w+ V( P7 w) m n9 y& ^typedef DWORD (WINAPI* TGetIpAddrTable) (+ r4 L' w2 u% \9 ^, j
PMIB_IPADDRTABLE pIpAddrTable,
/ E0 ]7 Q) a& y PULONG pdwSize,
' W1 q- M0 n$ \1 @0 J BOOL bOrder h/ g' r2 }5 g
);% M* I2 h/ { X" p
: G$ \9 ~8 P, W: j/ ?( l9 f9 I+ {: w- |4 a y% [1 f! ]
typedef DWORD (WINAPI* TGetIfEntry) (9 B# E) J$ |7 ^% p7 ]! T0 \
PMIB_IFROW pIfRow
! h9 V$ B8 T9 m/ I5 j);2 T1 _4 f, f/ x/ x. P, Z+ _1 J
- H& p* L' U: b. b& c9 @8 {
/ j) A4 A; o0 F% [CString translateUPnPResult(HRESULT hr);2 x& A, ?+ @0 x/ G6 w5 t6 r
HRESULT UPnPMessage(HRESULT hr); y- ]2 e# {7 d8 w" Y) Z4 Q; e
* R% n. [$ C* S' r& }4 v4 R9 N/ F- u& N" @6 E8 P
class CUPnPImplWinServ: public CUPnPImpl
1 q$ K# L0 z5 D: }+ s' H5 R" s' X{
% Y9 W( q* W6 O3 y1 v9 } friend class CDeviceFinderCallback;
3 ^% M$ Q+ k2 E+ o) |( P friend class CServiceCallback;
4 D, }4 ^$ r& g7 @ V; T- E// Construction: {* f$ [/ k( X) {) c
public:" f, q0 W9 g! j o
virtual ~CUPnPImplWinServ();. |' k/ o. O% ~6 I h
CUPnPImplWinServ();4 I) u/ t' ~, d* s- l, Y9 U, T
' R$ B( D: ?2 Z9 q- W
6 X4 O$ R& h% ?2 N: _0 A: p
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }
$ D$ Q. G- @; v2 d virtual void StopAsyncFind();
9 B7 w O, d5 D" j% Q2 I( |8 }3 u virtual void DeletePorts();
9 |0 S* F/ m4 ?. j1 ]! c virtual bool IsReady();
% `( a% b, X$ U, U6 }/ \ virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }
' z) U2 Q+ w$ U T& B+ ^4 ^: \1 x" u9 R2 v, x
( O, P/ O0 G0 P E7 l/ n4 g
// No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)
+ F, Y$ j1 {4 J7 z7 Z // the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later
4 H& t. k: s) T! Y/ R$ a virtual bool CheckAndRefresh() { return false; };* w" b- D8 M$ b$ d8 N/ K' {& p5 g! j4 k
: {. Y( E* C% [8 Z% l5 l" e9 O" \
. w; ]" ~/ }! s; [" [
protected:1 _7 m/ ]3 c) ~, ] t' s
void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);
. i: Z% p w3 c5 T) r! u9 V7 |; x% k void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);
! O" e2 K0 \7 W3 k6 c void RemoveDevice(CComBSTR bsUDN);
# T8 f& p' k# S* j! @ bool OnSearchComplete();
* Y8 @& K5 G4 i9 e: O2 d void Init();/ i0 T; k+ u' b9 e% L4 X' K0 R+ E
4 A/ |/ O |7 o2 E
: P7 I" x: S; _3 ^4 m; {4 `* J inline bool IsAsyncFindRunning() 3 }* F+ f& T' Q1 @: S- s
{; \& `. D) i) p; j$ r* K
if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )
; Q, c9 x4 F4 X" x {$ V) c3 R& ~" _- F
m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );$ C9 V8 D. ~3 Q: b0 B7 z
m_bAsyncFindRunning = false;
1 a A% ~ R3 ]* M8 \0 u }
' L, f+ S1 S. Q' R MSG msg;
# e) w* L" f- Q' o while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
9 e# G+ A/ d8 p Q2 o) e. w- | {
) l. e9 s' y& v& b6 B TranslateMessage( &msg );
f/ [# [6 Q5 {9 ^/ x DispatchMessage( &msg );# u3 _$ Q" j: Y8 @' {
}# L( h$ E, M# y, a
return m_bAsyncFindRunning;
% ~8 v2 y# a+ m' K }- m, J# G# d9 O$ I
! c9 Q" `4 T: N- u$ X3 S; m! W8 Y: F/ P3 N* F
TRISTATE m_bUPnPDeviceConnected;
8 ]4 X1 L ]* e' X5 ]* w" n: f, o
+ l2 {% ^0 t% r4 l. H9 \0 ?1 Q3 K6 M& V
// Implementation d) p/ b$ q/ s8 N* R# Z, H3 _3 v* Z
// API functions
; X6 N! l3 V& c SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);- ^/ q. n v& u" Y( Q4 B
SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);# x# G: S0 f& ^; d
BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);
6 p$ ]% y, _: p BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);" V! Y N+ ?1 M: l- A
BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);4 _. \' y/ o! m9 l* O4 m
BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);
5 h; d! u3 p a0 o4 Q6 h+ m) X- }( O/ E% V8 e7 |
1 h( H8 f1 H* d5 y
TGetBestInterface m_pfGetBestInterface;* L- V$ t5 {+ q2 ]
TGetIpAddrTable m_pfGetIpAddrTable;! K2 ?" v" I; j/ ?1 E
TGetIfEntry m_pfGetIfEntry;
N$ ]0 }7 v- C" h* m
, X: T* E; z1 K3 l; S1 W
/ e H d9 Y. z9 w2 P5 B static FinderPointer CreateFinderInstance();
, U# G+ g9 P$ _* ` struct FindDevice : std::unary_function< DevicePointer, bool >
+ L% E6 O' y6 A- s {' w0 k0 Y# m5 K$ K# Z
FindDevice(const CComBSTR& udn) : m_udn( udn ) {}
; p0 w# y, l# d, ` result_type operator()(argument_type device) const# p7 C% O4 N2 f3 T
{
, J' w. ?+ t' G$ T2 A) G: y CComBSTR deviceName;/ o3 [3 p4 `. N3 a
HRESULT hr = device->get_UniqueDeviceName( &deviceName );( [$ H5 A n4 t9 [) P" l
6 z/ {4 o. X5 c+ w
- u+ Z B) p) r0 I if ( FAILED( hr ) )
% |! g, N' B: | return UPnPMessage( hr ), false;
( q5 Y+ U k I3 S0 D# `7 d- M8 `3 r4 |7 ^3 L) l( f
3 L4 Y% W/ u5 |1 }; V C return wcscmp( deviceName.m_str, m_udn ) == 0;
% c, w: O! M" }. U' W" ? }# n. G& ]# `( w/ h( h
CComBSTR m_udn;3 G# i; b6 w- n7 `/ E/ E' a
};
1 v: F( I1 a0 k \% _ X
- h+ k* G- t; e/ h; p void ProcessAsyncFind(CComBSTR bsSearchType);9 F& ] N: a2 U
HRESULT GetDeviceServices(DevicePointer pDevice);
- H; Q* `8 C, O. E' i: z0 m void StartPortMapping();& |. L% O$ n- z3 V
HRESULT MapPort(const ServicePointer& service);* R5 P: h# f" h. s
void DeleteExistingPortMappings(ServicePointer pService);$ G% M. g; `4 ]; V7 ?/ u
void CreatePortMappings(ServicePointer pService);
$ s9 {3 U) G5 e' K HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);, J" [5 y: v6 K9 A
HRESULT InvokeAction(ServicePointer pService, CComBSTR action, % b/ [ c. l: S+ |
LPCTSTR pszInArgString, CString& strResult);
% v1 e* c v* b2 {" |2 Y" n void StopUPnPService();" P0 |1 ^7 |9 D$ q
$ _0 p# q5 e+ z" V6 I! ?- \# j! m ?( A9 G- O5 H% g4 V0 }& }: _
// Utility functions* O* ^' N8 ^- ?& [8 d
HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);6 e3 X4 \3 B# p. y$ Z
INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);
& q( a5 k3 F9 A/ c: q% @6 f INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);
# r. [) g* c4 z, ]0 O8 j* u5 C void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);7 {' H( f8 {: V
HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);
" y( D) f; D$ E7 Z HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);3 P9 ^# Q2 Z) t( m* V8 r
CString GetLocalRoutableIP(ServicePointer pService);$ E$ ~0 o* c" C
7 L6 v6 [% B( e6 ^# d! V) ]1 n
, P: S$ }: d( I3 |) C9 `1 Y: \& M. ]// Private members7 F& N9 F" Y$ ?6 \8 I8 Y
private:# N& w8 E5 s4 y1 A% g: `' U' A- u- I
DWORD m_tLastEvent; // When the last event was received?$ O$ Y4 f: [9 @+ L" N
std::vector< DevicePointer > m_pDevices;! ?# n7 x. U3 Q. B7 Y
std::vector< ServicePointer > m_pServices;
9 @5 a% S% g# u0 p) t FinderPointer m_pDeviceFinder;
# k% H" B8 d8 g" y: c DeviceFinderCallback m_pDeviceFinderCallback;
) h. W0 W ~6 n( U3 b" @6 }4 ^3 i ServiceCallback m_pServiceCallback;
2 b% ~( G# h6 b6 D, R( X. E
, W. P) U+ x/ Q9 h0 a; Y# O, T: v( ], ~1 C, L% }, m4 A! Z
LONG m_nAsyncFindHandle;
2 \ y' E6 R0 s3 M bool m_bCOM;2 R% ~! G" S6 P* N2 J3 g* b! Y
bool m_bPortIsFree;3 T- T D( k3 j* m$ u/ X; p
CString m_sLocalIP;0 j! f* I; c0 D! v7 H
CString m_sExternalIP;
" P9 A+ z7 ]1 }% |0 l$ f bool m_bADSL; // Is the device ADSL?7 z0 a5 `% z' F, T- ~8 w+ H9 P
bool m_ADSLFailed; // Did port mapping failed for the ADSL device?* M5 r% P7 T. G
bool m_bInited;; z8 R! e4 q2 D* q1 @( N
bool m_bAsyncFindRunning;
- ~" W6 [# |* A# R4 Z HMODULE m_hADVAPI32_DLL;
9 f5 s2 [% f3 k! U/ R7 a; y HMODULE m_hIPHLPAPI_DLL;
9 ~; h% H* U6 R T: B: E6 z bool m_bSecondTry; v z9 P! `! k5 T2 D- B
bool m_bServiceStartedByEmule;9 |2 @* O1 v7 a+ G5 \" I, I
bool m_bDisableWANIPSetup;" ]: [2 n) @0 [6 g$ W' _& V' o
bool m_bDisableWANPPPSetup;
3 o- c: `' D- t7 W6 `- s
* F; K% i# k% ?5 _2 Y- t" E/ P2 T& u2 u
};
8 s( `& S' f: [) e* r
) V% k) M. T9 h5 W4 B+ K" J$ V! _6 [. Q7 e ~
// DeviceFinder Callback
) ]2 X# b' j# s/ V* ?class CDeviceFinderCallback+ N% H- _# g' a% l3 M- U
: public IUPnPDeviceFinderCallback5 {! A0 S3 X8 B3 E# ~ p
{2 d7 h* F' c- O
public:' f% I- r5 p$ q" [( H# e+ v
CDeviceFinderCallback(CUPnPImplWinServ& instance)
6 E: Y+ C1 X6 u. Q : m_instance( instance )( p/ @: B5 k+ H3 A1 H
{ m_lRefCount = 0; }1 a2 s" k! ~) l/ m6 t- Y2 [
/ X/ y+ r+ N3 R1 I
3 O! B% e+ q7 ]2 T# Q$ I! ~; s# G8 _ STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);; ?) Z* v/ k2 | R" ^+ c- U% Q' }
STDMETHODIMP_(ULONG) AddRef();
r$ w3 h1 Y$ [% [4 N( r! M, F STDMETHODIMP_(ULONG) Release();
0 A" B: d# [' E# F6 Z# {. P# ^ H$ ~: `0 M v7 ~9 O$ ^+ W* O
, D# o. H" y. }+ M// implementation
; S5 s/ ^1 K1 {. d V7 W: Eprivate:
U% J( ]* i Z' B. I: d HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);) z. D1 l M$ r1 n5 z
HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);3 o2 m4 h( J' G$ M- h0 A
HRESULT __stdcall SearchComplete(LONG nFindData);8 \ H! ?9 x. b' n8 l
$ ?0 O. S5 O& g1 n# v j9 k0 k9 u) u$ B" u. b5 |
private:- Y, V4 F9 m7 n A8 _
CUPnPImplWinServ& m_instance;
: A3 N5 ]) b, q( R' v6 v7 c/ ?+ _7 l LONG m_lRefCount;
5 r7 v2 O0 }. ], M1 K};
* ?+ l1 L# X2 r2 T U+ V }
7 h' p; X# }; g, Z1 ?( ?5 A# ?2 R6 y; _: G! @
// Service Callback
. I T4 d' o; ^( T1 L' ^class CServiceCallback
& j$ l6 p' c) T9 }' n : public IUPnPServiceCallback
2 ^6 `# w5 P5 v+ X0 c( ~9 c+ M: m{
: w! _! A1 e9 `1 _public:. V# d- a. b4 |
CServiceCallback(CUPnPImplWinServ& instance)( i9 }, @" V4 P3 P4 c
: m_instance( instance )
" |* s+ B* X h; ?. ~9 z4 [ { m_lRefCount = 0; }
{+ a$ g1 d' f8 F8 U. ~ 0 Y' M" s h7 q' {: y1 h3 \
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);& m# p6 h9 L4 h: _9 w, a
STDMETHODIMP_(ULONG) AddRef();" t: [1 M$ E( f. g! p1 K
STDMETHODIMP_(ULONG) Release();
7 X" ^: A/ `+ i, O" D0 \. j. l2 F$ _: x1 v
' b4 `% q3 |2 |/ @8 `
// implementation# m9 w6 H% v# @0 T) p
private:; B5 D6 Z9 O. a
HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);
8 g5 [ V6 L, z) ] HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);
/ C. y) a5 k) ~# q7 S+ _- L. ~; B9 C( ~
2 k% E- M% m- ]7 E8 x( H" o0 [
private:
2 r, B' N- x7 u7 i. e `6 f CUPnPImplWinServ& m_instance;: s/ r% I: q/ j8 P4 X3 l5 }% I
LONG m_lRefCount;+ M4 S1 R5 {' Q. a( \- t, E. T2 Y( e
};
$ \4 N; e/ h5 ^2 n, D! U, D/ i! v) `# W8 t! G' z" v8 v2 [/ @
2 O3 }' B; }' b/////////////////////////////////////////////////
* K- M: Z9 a5 |; X5 z: ?3 S7 C/ x
9 e9 U2 Y+ ^( x4 q# d/ I使用时只需要使用抽象类的接口。; m5 l, y' y, w
CUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.
8 o* l" E) A: M) z }6 TCUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.5 \! N7 l; f; ^ c. p7 M
CUPnPImpl::StopAsyncFind停止设备查找.4 c, m" q( ^# s, r3 ^' X0 R4 M
CUPnPImpl::DeletePorts删除端口映射. |
|