|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule,
. a ?- z# S6 H, i4 p% |# _8 m+ J
. R, ~1 B! n# H6 l3 }. t( N% J///////////////////////////////////////////
5 g; B% j9 O9 G. W3 d//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.4 g+ H5 e- m6 P+ F& M
' F/ e. \ S! q* r; |/ v. Y
$ J9 s. Z8 Y1 ]/ C: w
#pragma once4 A% ^$ b7 N# N/ o) b6 P
#include <exception>8 e! A+ h b/ g# o" L8 ^( V
`, T; T" F' Q0 E0 ^0 y4 @- |* z9 P8 g/ h9 e
enum TRISTATE{
0 V: _& @/ G/ \3 u% b- p# ]- l TRIS_FALSE,
: E$ O0 w$ U2 _1 t t TRIS_UNKNOWN,4 C! {- l0 D7 `6 I% y- [* L
TRIS_TRUE% K- M8 N' `# B9 ?. u
};2 J, x. ]; g7 {( h) o d+ S+ h
! _7 y( E: \0 E4 O' ~, w
# x( V F2 U8 t7 f. g" _enum UPNP_IMPLEMENTATION{/ M. x* O- d0 J! q- V
UPNP_IMPL_WINDOWSERVICE = 0,
) Z1 {- e3 U5 ]% a' ~6 p8 U UPNP_IMPL_MINIUPNPLIB,+ _ P& F* q0 Z" E' {
UPNP_IMPL_NONE /*last*/
* v9 |& X" C/ O, K};
5 ]3 m p% u/ T B' N& G0 O' ]# u! m- e v" t& U
( e5 x- p4 `6 N( m. a& T
* A6 o6 s8 i t& K, t7 _* k- X+ b7 E$ O7 i% e, x
class CUPnPImpl
4 u, v* Q, g% ], x{
% |3 }& e' D( x; k) x& J: ?public:( L" A+ B8 ^8 I6 S/ Z
CUPnPImpl();. `4 `$ e2 r k: K% _
virtual ~CUPnPImpl();
* R |* ?. S" K( v struct UPnPError : std::exception {};
8 W( X! Y# ?, O6 g! y9 C enum {
7 D8 ^* F& l d, A. \ UPNP_OK,& ^+ T' V2 D* x4 |' [- B
UPNP_FAILED,* G1 }5 |" w! A5 B
UPNP_TIMEOUT
4 a# G& H5 j, F };
0 `$ p. f2 m( Z5 G( Z2 [7 ^% o, u: N0 ~3 F$ d; L+ D1 c2 x
7 R# l" J" S: w# `8 n0 @& ^
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;
" T' Y; r) ?2 R0 k1 D7 D, } virtual bool CheckAndRefresh() = 0;
+ \/ V5 `6 Y. O1 J$ b' h virtual void StopAsyncFind() = 0;% f1 `5 {1 A* s; Y9 c
virtual void DeletePorts() = 0;
' n' w9 z0 L1 j5 L/ j. e virtual bool IsReady() = 0;, N$ t' A- a& k) h. x5 {* E; a9 K
virtual int GetImplementationID() = 0;1 k* K, W' ]; w# b
+ V) l/ m: O& Q" L# y2 r$ j1 H% Y
void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping$ z! T; Q$ J. W- [; `. }
. U; S" N, @- ?
7 _( N5 W8 J7 N7 H
void SetMessageOnResult(HWND hWindow, UINT nMessageID);
$ o8 t4 p, q' q4 ?$ v' t( i5 S- G TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; } U5 }- X8 t+ S1 S5 T
uint16 GetUsedTCPPort() { return m_nTCPPort; }3 C' S3 Y) A2 ?" R' q* C+ }
uint16 GetUsedUDPPort() { return m_nUDPPort; } 1 R4 K6 ^6 ? w; h
; a$ T% ~6 [) ^1 |6 m7 J
, g; Q+ ]% s# X// Implementation' X/ B+ N3 N. k$ }/ r8 A
protected:" H, c# d3 o& H/ S& G: W
volatile TRISTATE m_bUPnPPortsForwarded;
* B9 l8 G: G8 t4 V G void SendResultMessage();$ @* k& ^! Q% {# ?( a
uint16 m_nUDPPort;* \; P% \) |3 }+ C* x2 m0 E: _, w
uint16 m_nTCPPort;0 l& [. v& n1 d/ y$ S$ q6 p
uint16 m_nTCPWebPort;# U, h/ R: P; ?4 o2 M
bool m_bCheckAndRefresh;
3 E1 L7 s% y; F1 c2 r
% v1 \% ]. @7 @9 Y0 T
- f g. x9 q! V: J# Cprivate:" d. w- k" x" I6 j( g4 T/ c
HWND m_hResultMessageWindow;
# G4 f, Y+ |. n+ P( w& s UINT m_nResultMessageID;. `8 {$ b) p- S2 o! o* _+ Q
% Q! Y6 Z& ~" M2 |0 T: G& k; `
" d& w9 h5 ?+ z9 [};+ A/ O6 g( X' E1 o$ v* `& H( G: ^
9 A# w6 Z" S0 P' H( x( n
* F" [) p. k) g
// Dummy Implementation to be used when no other implementation is available, `# B+ [; }6 M/ G; { S* \. ]( l( R
class CUPnPImplNone: public CUPnPImpl7 m" V: Q( k% `) y6 E: L5 s1 a7 e
{1 K4 C+ N/ {1 ]/ b9 r) Y$ z! k
public:
/ z9 N: `; x3 ^8 U9 Z virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }, y2 V; B4 C0 }* s' Z
virtual bool CheckAndRefresh() { return false; } x& S( p& r: X& f/ [
virtual void StopAsyncFind() { }4 k2 y$ V3 k5 O% C) a! s2 C
virtual void DeletePorts() { }9 \3 v4 Q* L T& S. N" A" v- M
virtual bool IsReady() { return false; }+ u/ P; m& _# @0 x" w% X
virtual int GetImplementationID() { return UPNP_IMPL_NONE; }& w' j' z$ F) Z& p: p0 n& o
};
+ h. Z8 k# U7 y9 @8 f m5 w" {
6 ?5 O1 q) A" _& D7 Y( n, A% V/ z5 d& d/ \# C3 X: j' i
////////////////////////////////////// e1 ]7 u s- ], `" L4 t7 s$ Y
//下面是使用windows操作系统自带的UPNP功能的子类! f4 l- i, W$ c9 ~
0 [1 M4 t4 b: @" r7 R$ P( Y& @# f7 ^% Z, \1 g& I) h/ p
#pragma once
! }1 G3 K& a& _+ I' y#pragma warning( disable: 4355 ): [5 ]4 {' L2 q' |6 | \: ~
U. N/ M+ N$ o
( j9 C, l+ h; M, a#include "UPnPImpl.h"
( C- q; t% T6 T3 _ E1 W/ b: A#include <upnp.h>' Z |& {5 Q, |' s3 a
#include <iphlpapi.h>
S* |( w/ u" _#include <comdef.h>8 H4 f# s* |/ @7 q B
#include <winsvc.h>2 V+ i& Y2 j7 @' l, Z8 h
* L6 C3 ?( B) m
% ?, N) \8 g4 h; S8 z( u#include <vector>
* K; Z( F& s: P, J: j#include <exception>/ n* H1 ^9 s5 X/ ^3 t
#include <functional>
8 {# K6 G, R1 w S. y2 t
: c1 s* I0 Y( ^
! S1 h4 ^" a7 X- d5 {5 a* h2 \
4 P+ O3 ~" W K+ L* `5 c8 _& W: b
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;% z; U4 K! U& ?; ]8 q9 T6 d4 t' T" a
typedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;2 J$ d% a. A7 K/ Z7 ^1 k& s
typedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;
5 @% S" ?: Q5 Wtypedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;
. G& m' a3 Y* w3 vtypedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;
$ b2 o, G* _% w5 Q! _) g+ `typedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;
! P$ ^) s* r! C2 I% n7 wtypedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;
1 I( x) B# ~2 h) o! [# z, @
w \3 p, V, P" @& f( q
, p: {0 O7 `- C1 \* p* b% M9 dtypedef DWORD (WINAPI* TGetBestInterface) (
, w5 l4 b8 o1 e; X IPAddr dwDestAddr,
6 s: a9 |" T$ w* f$ p% O- T: Y PDWORD pdwBestIfIndex
# L. a" I; C* G$ d);# _6 L) _2 M/ Y2 t, {
: [- Z+ O, e( ]* F8 I6 \2 {6 Q$ E4 S6 H( \* }
typedef DWORD (WINAPI* TGetIpAddrTable) (
4 E% m" C& M, _5 a9 } PMIB_IPADDRTABLE pIpAddrTable,* O$ N& l" m" ~8 @6 i$ S. i3 F! }$ B
PULONG pdwSize,
- _5 Q. D) u+ {; Y BOOL bOrder' ]3 @6 }+ k- A
);2 R4 B# u# T0 b6 D' q" {
6 {7 D, `; S! `8 g* r, W7 q/ b3 m) U* z
typedef DWORD (WINAPI* TGetIfEntry) () [, L/ t9 z. c( e7 O
PMIB_IFROW pIfRow
5 e8 W N& n' V: q* _);
/ ?% o! _$ u7 L a. B: m2 E0 L; S0 r& ]0 H
R& D3 O0 F! ]0 L- I4 dCString translateUPnPResult(HRESULT hr);
* c9 E1 h7 ?+ p1 fHRESULT UPnPMessage(HRESULT hr);- n5 N& B+ L/ P
7 V- ]0 \/ H, R7 I
. l6 x" r$ w1 ~+ h+ jclass CUPnPImplWinServ: public CUPnPImpl r! K( X+ a" |" t; E j
{
0 O" V3 F' Z) e$ z$ [ friend class CDeviceFinderCallback;" u& b. D0 \) l) N2 Z
friend class CServiceCallback;
$ Z* j1 C1 D; X, y3 p' B// Construction
& c& J1 R: X, D2 Epublic:
$ _8 f" l: B9 y& |. j5 \" c virtual ~CUPnPImplWinServ();
6 B% a* T! J2 X4 s; V CUPnPImplWinServ();
$ `: R# J7 h. F+ e! O
! X5 j* y5 i: c& F( Y. W
0 O- X, M% O+ K4 F2 X3 j virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }
1 W# Q* b4 `! Y. c" a" q/ y virtual void StopAsyncFind();
* A; U% I1 I2 h- b. o5 l virtual void DeletePorts();1 j t0 Y) G: [: V
virtual bool IsReady();
4 c$ j' W* J) K" @ virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }, I' U1 ~6 N4 ?% f1 Z; _/ a
3 U* |1 q) K9 V. w
8 k( t- V0 {; P: x; P // No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)
4 P* O* p5 B8 l: g. F // the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later; r4 j" } l6 d
virtual bool CheckAndRefresh() { return false; };
/ A! c( Z' i o( y) p- d% K+ m$ o) @* G, I7 y# n( w! q: F& K% S3 x# I5 D
8 c* L+ U& X4 b# {0 G5 u. r4 Eprotected:
! \% n" I6 c' Z: i+ f) L/ ^0 u void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);
9 I7 o: G9 D% e/ E void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);
( Y. H7 m) x5 D. C1 g, M1 X void RemoveDevice(CComBSTR bsUDN);1 M. o! o1 p" K$ f& d& u; L- _: _* u
bool OnSearchComplete(); g% ]! ^$ Q3 q" ]% l
void Init();5 Z0 K; {+ e* h9 D+ V
9 j: c& ] A& ?' n, C- _
) B& S$ y0 M3 J8 G inline bool IsAsyncFindRunning() # N6 b& T# p) D1 i
{9 k2 X4 u9 \, D `! a* Y
if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )- C" z( a2 F& \
{6 G0 F9 Y; E8 R
m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );' G7 ?6 A7 b5 q6 q+ z. z v
m_bAsyncFindRunning = false;
* x% I0 w& k$ \9 t }
5 d8 E {; ]( c MSG msg;8 h6 s' g7 X( A. l, o
while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
$ J6 z1 U. j) _) G- } {
" p2 A+ J0 A4 } TranslateMessage( &msg );; \+ U( m4 Z6 B7 u% N- r4 |) j/ Y( O
DispatchMessage( &msg );/ x# O) z" y4 G' ?* d6 ^
}( p. p* A' @/ X7 ^
return m_bAsyncFindRunning;
4 r. C. ~& y9 l9 W }
* K, l' v9 A9 A& i# {8 ] v* e2 |0 L& ^( Y- |! @- ?& M% X. I L
- {1 I% w- a; S* x9 w! U1 @! A! ?! N TRISTATE m_bUPnPDeviceConnected;/ }0 \7 K( Z# n/ M7 v- m
, ]5 N) t5 }! q" y$ w8 x1 s. G0 k% o; A" X( Y, {( [8 Q9 U8 K" g2 K. B
// Implementation5 J/ l& u# A8 Y* q
// API functions N3 r" {, v4 F% G& r- V6 u$ p
SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);4 `. p" Z9 r5 l" f9 r
SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);
" T$ m% ^- P, o BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);" w0 B- C" _. Y, H( N
BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);
0 h1 k5 N4 N1 A3 P' q2 J. T- W! d BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);, P5 G! g9 M: f/ M m
BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);" W! B& k( T! W% o9 p5 ~, \
/ X# o" l E( n! |$ c$ b- C5 k
8 L+ G: Q/ j; Y6 X+ X/ d0 R
TGetBestInterface m_pfGetBestInterface;& ~0 M# U; f, B% C
TGetIpAddrTable m_pfGetIpAddrTable;/ C6 m: V6 A! f% J4 l
TGetIfEntry m_pfGetIfEntry;' h. G8 h) W- i# U+ g) j
l$ e" b. c% d
0 z1 p2 q, E# t4 E7 n9 } static FinderPointer CreateFinderInstance();; v) r/ i, ^2 b
struct FindDevice : std::unary_function< DevicePointer, bool >
1 h7 L% p9 _9 |. m$ `4 S/ ` {
; q- F" E- J- v" D FindDevice(const CComBSTR& udn) : m_udn( udn ) {}
' F9 n/ q' d' d i result_type operator()(argument_type device) const1 L! y% K" S: T% y8 Z. w! x
{( u5 c# k# x7 L/ I0 n V% w0 e; O
CComBSTR deviceName;
( S$ Z; T6 w- N3 I8 p( ~' U; d HRESULT hr = device->get_UniqueDeviceName( &deviceName );
. H' v; A& r- i0 s4 N! S8 v- \4 [7 S1 E/ n7 `6 o: q0 q
2 n3 ^5 q5 m2 ?( s if ( FAILED( hr ) )( E o, d N: Y+ U
return UPnPMessage( hr ), false;
+ A1 E3 ~3 P" j/ u5 @3 Z/ G3 v; _5 c/ }2 T ~
: e; z) J& n1 K a+ V6 x1 W return wcscmp( deviceName.m_str, m_udn ) == 0;
8 s8 V' y @# X1 I4 b0 ~ }! k) Y) v. N) {2 D2 U7 g: k
CComBSTR m_udn;
3 j( ~7 N- u4 ^9 Q };
$ H' ]3 |6 Z g! p0 \* A) F
7 t3 E( |3 k7 ?( r& H9 h k void ProcessAsyncFind(CComBSTR bsSearchType);
! C# D& m1 |: y/ i HRESULT GetDeviceServices(DevicePointer pDevice);
+ g, L/ Y& a9 c" W void StartPortMapping();
- I4 z& F. O8 l' ]7 e HRESULT MapPort(const ServicePointer& service);0 v+ T9 [7 X5 w# ~& A" }5 U0 ^
void DeleteExistingPortMappings(ServicePointer pService);6 l/ j1 x$ N0 i2 I1 ~
void CreatePortMappings(ServicePointer pService);2 A! A+ x! \: B. S" I
HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);
' Q8 }7 x" {6 y `! ? HRESULT InvokeAction(ServicePointer pService, CComBSTR action,
3 R+ l+ x% W8 w, v. e+ o LPCTSTR pszInArgString, CString& strResult);
7 F: V! M3 u6 q: I void StopUPnPService();
, k6 Q& ~- E9 j" x- X% E! k; x; U. Y3 k6 v
6 @" s# W, u8 s: t3 Z4 F+ [ // Utility functions
( _ A: @# O; e0 f HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);4 v8 T5 A7 {' u
INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);3 u. M/ o9 W' C
INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);: |% e/ Q; |) F2 {2 b. w& O+ N# E
void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);
" ~- f! T) n0 I HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);
4 o. \+ J) j0 G3 O, w HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);
% q* U8 `- `7 h CString GetLocalRoutableIP(ServicePointer pService);
; ^, W* B1 B# @6 @# G
- v9 T3 [& y6 `' O* l5 l" q" e4 P; [4 `8 C; t) e/ k
// Private members5 ]1 @. f7 z; X+ i3 `/ |/ {5 i# I
private:
3 h7 i8 y. V" I( I DWORD m_tLastEvent; // When the last event was received?0 R w! t2 x0 G: J" ]
std::vector< DevicePointer > m_pDevices;
3 [5 R, F2 W6 l9 p std::vector< ServicePointer > m_pServices;
( a' j2 h, `" K3 @ FinderPointer m_pDeviceFinder;/ c) v* x+ m2 G/ w( W8 Y
DeviceFinderCallback m_pDeviceFinderCallback;* [: n ]9 u7 {4 e* K) g5 c% X! a
ServiceCallback m_pServiceCallback;$ C+ [3 A# r) w% n' M
1 K! E, h: V+ z2 r% k8 b
5 y9 T& Z7 {' O8 S8 A3 q LONG m_nAsyncFindHandle;
$ @8 u( y1 S/ M% Y bool m_bCOM; x; Q+ i f5 K4 C/ U- j
bool m_bPortIsFree;
7 _6 C. G! s V% k" q' G CString m_sLocalIP;
+ z* H! S( _) f' b- j: ? CString m_sExternalIP;' |: ^" L( I# s: B# d9 v
bool m_bADSL; // Is the device ADSL?& U) h/ Z) S. j0 c! {
bool m_ADSLFailed; // Did port mapping failed for the ADSL device?
0 ]9 U5 ^: d( S" ~ bool m_bInited;
& I& R _, e. m2 y( j bool m_bAsyncFindRunning;
$ p# `; i7 H G5 v HMODULE m_hADVAPI32_DLL;
$ Q0 {+ U) a3 r4 ]& @* U$ Q7 z% | HMODULE m_hIPHLPAPI_DLL;
$ J% c1 @. R2 ^2 D bool m_bSecondTry;6 C/ }% T0 @+ S/ ]: l; [ F
bool m_bServiceStartedByEmule;8 c6 S2 h/ C( G) j L% O4 J k
bool m_bDisableWANIPSetup;
c: n5 f4 \6 n, w/ s6 p bool m_bDisableWANPPPSetup;
7 ?4 a8 {* C; ^+ d1 ?5 X3 P* w. k/ D1 _0 ]! u; G
$ B4 l- n7 V4 @+ R
};
) \ ?8 b+ Y/ _" t L1 V" R& }% I3 d/ D
* V; h7 _- A5 T* H% G- G// DeviceFinder Callback6 X# N2 ~4 W4 t. O$ r
class CDeviceFinderCallback7 b. [" c' W/ P3 y( N
: public IUPnPDeviceFinderCallback
& w& W) t( b/ `1 r( [{
q. @* `0 r4 ]: O& R# G, Xpublic:
/ V8 n+ `2 K9 e1 w2 x0 N, Y2 ~ CDeviceFinderCallback(CUPnPImplWinServ& instance)
- j. g. ~- w8 \% [1 R9 b : m_instance( instance ). Z5 ~! P/ l9 C G( T9 a3 Z3 f
{ m_lRefCount = 0; }
0 x" d, h$ e3 Y1 ^/ ~4 p- d& X$ ~, w" i0 _/ i- Z: ?
1 X w- W! m* `' F) M STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);7 u; O! X) l7 g
STDMETHODIMP_(ULONG) AddRef();. ]+ U+ ^0 {2 i( t8 L
STDMETHODIMP_(ULONG) Release();
( r2 V* U7 \/ H4 v7 J+ V; { h
) m, a7 n2 p& G- ?' z( a2 P& J7 ~0 G# ^3 h
// implementation2 P0 L8 @( `! u- R7 \
private:
$ t% u# c6 H4 V' o" ] HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);$ V4 \ _* s: n ^1 J/ W$ X
HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);
: D9 S1 u @, F5 R7 ^1 _5 z HRESULT __stdcall SearchComplete(LONG nFindData);
& w: J& I5 x# f2 P9 {3 N N1 t# ]. o% s5 r
- |" @ d2 O; _
private:
: p2 `3 e6 [* j; v! ] CUPnPImplWinServ& m_instance;
" e9 N2 G0 W1 h! c& c# D O7 u* x LONG m_lRefCount;
- c9 |5 J, { K# x g" l$ |};/ F3 m- v7 l: J4 p1 @
+ [& j+ Y* ^% ~# p* ~" y
( T5 ~3 d. [+ I# ~& F. M3 `0 U
// Service Callback 2 P" p2 Y. K3 w; m
class CServiceCallback
: x8 l* d s/ N: w8 G" \ : public IUPnPServiceCallback! h. F, K' |6 e4 ]
{
`# K* x# v6 ]/ ~; w2 Gpublic:
* v2 X5 c) e+ f, @9 x4 t CServiceCallback(CUPnPImplWinServ& instance)
/ q4 D: t# \8 a' ]' f3 n) @% U : m_instance( instance )
* n4 P* T5 \+ R3 z { m_lRefCount = 0; }
7 c5 y) m9 h# J M ) [" p* j) R5 x% f- ^. i; m
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
1 R3 z) }5 J2 Q+ N5 L STDMETHODIMP_(ULONG) AddRef();
i& {4 X. @1 l0 @ STDMETHODIMP_(ULONG) Release();
" k6 ?" i; _% J. ^+ h6 O
6 P, j% k3 Y( @$ N9 V' x, e: Q+ ]( W( q* E; w
// implementation
- N! ?+ `( j# G8 R3 Jprivate:, q: O6 m* F. w7 | p, W
HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);
8 V4 {; u) D, g HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);3 j; M9 P( t8 u" F( h
( x# x) t" |* B" t, f7 x9 d
# y: q9 x+ w9 F9 Y7 d& rprivate:
4 H& {( s3 b: j+ s- J CUPnPImplWinServ& m_instance;
x- H0 J0 u% {$ n) @. o LONG m_lRefCount;
& E( N( F7 `8 u% E' x0 J( s};0 `# g( y% |3 U, h- v6 _
8 B- }8 W" p* s8 D6 l
* \6 H% Y$ W; @/ M* x' T/////////////////////////////////////////////////) p. c J# q' M+ n; |2 `: v
% f: b) W$ T9 O* L+ [6 S
4 A) S( O' l1 i$ x4 W% B
使用时只需要使用抽象类的接口。
4 D, f$ U& ~/ k& @1 p. r6 DCUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.- H& x8 |1 {" K/ a: P2 |3 o+ N( C
CUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.
0 O* P5 Q6 n* z# WCUPnPImpl::StopAsyncFind停止设备查找.
( _8 c5 ?9 L% cCUPnPImpl::DeletePorts删除端口映射. |
|