|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule, X* |: M% ^- `5 N5 Z8 n! F2 X$ ]
; P; i# a8 S6 Z3 c8 {2 e( E& }5 P, V9 |
///////////////////////////////////////////' T8 }% t- l: I5 {% B" h0 E
//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.& l- j( |. z! n) s) n( |
6 l' `6 B7 y4 ~: S! S. e( K; [; n* ^5 `9 u/ w% J7 P2 _ ]- ]
#pragma once
( W9 N5 \) U9 g#include <exception>3 T- \2 S: ^' V! D( ^- y
0 X* B. ^) {* a n1 |8 ?
6 o; D: a; @ U
enum TRISTATE{
# b8 `2 u/ M# z" W- W TRIS_FALSE,
! l- {2 l5 o8 @% h+ }) a7 B TRIS_UNKNOWN,6 h: N" E" Z# i0 P: {/ _
TRIS_TRUE
* U- I# D+ ?' C7 Z' _};. @" M; s% K% D8 Q- U7 [% @
" W# z$ ~0 ~3 x' z! @; d3 D
0 O5 e9 l6 d* e( Z# [- N
enum UPNP_IMPLEMENTATION{
5 o/ U3 K- f6 ^4 |; k* Y: C UPNP_IMPL_WINDOWSERVICE = 0,' J" m8 h0 m; R" f: P
UPNP_IMPL_MINIUPNPLIB,, J: ?) o6 i5 E, v6 c
UPNP_IMPL_NONE /*last*/
$ g5 n0 A9 G8 f1 B: C};
: D5 z, `) F+ f6 G* ?; G$ T
8 T6 {. @1 @6 q% {8 L. Y e$ m- @% _
4 i6 k8 c P* A/ a
* d( T9 E$ X8 ^( w1 M8 `3 s5 [; E% [: K& o, R2 D# w
class CUPnPImpl
+ _3 C2 V. N3 x* O: p' R{# F( M- l9 S4 G
public:% K2 u8 U5 \2 Y! P$ b; O- {5 S
CUPnPImpl();
@ I( r& d1 [3 q* r virtual ~CUPnPImpl();9 y9 n; b- L5 e) q* J
struct UPnPError : std::exception {};! D9 t" N4 _0 B/ B. g
enum {
4 ~! ?( ~: q$ |1 h. `3 S5 s UPNP_OK,
; J( M1 E" e: }# P0 j; f# I UPNP_FAILED,
' ]$ X% W' ]6 F8 E UPNP_TIMEOUT
/ b! A+ A! n8 f, Q& K% t, C1 J. w };
+ |* l5 ]. T/ [& d9 k0 o, h8 _9 [' O% G, r. D$ m- S W
" W9 g8 a" V1 Y) x6 A virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;
2 X7 S/ i" H6 z8 i virtual bool CheckAndRefresh() = 0;. o. y6 s! ]- _% p) i5 o. L
virtual void StopAsyncFind() = 0;
' S9 u2 C7 D/ \- m0 g1 c& P virtual void DeletePorts() = 0; w1 ^8 b* ?, |8 g( X8 b; n
virtual bool IsReady() = 0;3 n: B7 r& g, O& D8 j" O# s; n
virtual int GetImplementationID() = 0;
8 [$ s% u8 Z* Q8 q6 `! t. H0 }3 g
- I& r! \0 X' Q5 t' j5 _ void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping: [% i9 [9 Q1 s7 L
* Q p0 R, t' X9 q- @/ N
" v" S" V# N8 [
void SetMessageOnResult(HWND hWindow, UINT nMessageID);
4 @6 l. H' U& o TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }! O$ R* T. K4 e! E- g" Y" L
uint16 GetUsedTCPPort() { return m_nTCPPort; }
9 O6 \7 X) ^% Q2 k uint16 GetUsedUDPPort() { return m_nUDPPort; }
8 t& `0 n+ U6 K7 x2 K# r$ W& a+ V- P% x/ i; H# _. r) Q
+ g& p) ~, h8 U1 v) l5 P5 ?+ [# h// Implementation, N; B) l* E: A9 v) B8 L
protected:, {- b b" j* z6 ~1 ?8 ^9 r
volatile TRISTATE m_bUPnPPortsForwarded;# ~9 j) v0 ?' C# C& n
void SendResultMessage();, [( T) U/ L& W- X* |+ c
uint16 m_nUDPPort;5 s# Z/ l0 ~- ]7 z. w2 ^
uint16 m_nTCPPort;
Y5 u7 I' ]0 y# C1 O, o uint16 m_nTCPWebPort;0 o: h9 _/ q* I$ h0 n4 E8 U
bool m_bCheckAndRefresh;
" y/ y7 F# y3 j/ Q1 E+ U$ L
' R* E$ @0 }' ?1 c# l
0 _7 P! n$ L2 S; b0 I# i% E& Rprivate:
$ f- o) S7 i' L HWND m_hResultMessageWindow;
! r6 C3 ~/ P! L8 J$ j! j9 g UINT m_nResultMessageID;
+ ~# D2 K' T# C8 c2 O2 l! M" s$ [ H8 ~. r: J, y. T3 f9 q5 |
N7 |" M+ |6 s( y+ @
};; @! M Q5 v$ s5 u+ j' l' z. d
- K$ x* ] I* |2 f, c4 N! Y% C( C; j' g* ]" g+ q7 e$ E
// Dummy Implementation to be used when no other implementation is available. ]( K( s; }, N7 s
class CUPnPImplNone: public CUPnPImpl5 ?/ K; q: [# K) T% p6 F. S" u5 o$ q; a
{
8 g/ W% {! x/ |6 P8 s4 i$ s' |public:# }* i4 H& u5 o% ?
virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }
f: j4 K5 [; y+ ?, g5 V virtual bool CheckAndRefresh() { return false; }
. o0 W. D0 e/ G/ ^7 g5 S: {' J virtual void StopAsyncFind() { }" s& J5 Y% \- ]8 K$ [$ k
virtual void DeletePorts() { }
# r6 v$ z( L8 F0 ~& ~ virtual bool IsReady() { return false; }
* D7 _# j% y# g0 }4 |- u% s) O/ a virtual int GetImplementationID() { return UPNP_IMPL_NONE; }
+ L( {: a0 ^, y- F' f};( x4 \$ z. [( U- c8 L! I( P7 x
3 `: w( i' b _
" n2 O& X, y& d; o0 u/////////////////////////////////////
, w- i* z* l) x; I! i- G//下面是使用windows操作系统自带的UPNP功能的子类
" D) U0 U4 O1 L T7 l! C
& P0 u5 b3 k( U' z4 V; F5 `6 ?/ C+ D/ F
#pragma once8 C% a7 ~& V- R7 M) ]" i
#pragma warning( disable: 4355 )
# k9 g* a- X4 a+ y: _' L) B# C+ k& K; y& H0 N$ O" N
9 n3 v0 L4 c/ R J
#include "UPnPImpl.h"
: s( v1 f, o n O" u: C6 }#include <upnp.h>
$ \2 P6 I* u& ^7 m% r7 L#include <iphlpapi.h>
9 M0 Z' |1 R+ z- W#include <comdef.h>
; x# E/ V' W0 M#include <winsvc.h>
+ L; R, F% y, h1 }3 _
" H: Q+ z U0 t
. ?: l' R0 s4 K9 L#include <vector>
' S+ f6 M' P0 f#include <exception>3 V, ?6 E/ b1 O2 N
#include <functional>1 ?6 O- c6 v- L
: N, K1 [+ G+ g, L$ u2 D2 F( W+ {& ]' z+ y) [7 Q: e1 T7 ~
- w, N9 [+ J; }$ R6 F
( N+ x3 Y) V* Q$ ^9 k# X6 d% Dtypedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;
- f1 r; I4 M; C/ [typedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;
% J5 c: M0 ^4 ~9 P! O7 T* B. Stypedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;
# E! b* {/ o( j! P3 S+ k. wtypedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;
0 U# @3 K7 ?6 q# [% Y' @typedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;( g. a) v7 S3 ?
typedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;
# d, x) m: w y a- z+ Ftypedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;. ~, P- A0 Q( H0 O( x1 D# V5 q
( J4 ~, g0 X( A5 i
; N5 _ Q4 h9 ?6 `( _& w1 @5 v
typedef DWORD (WINAPI* TGetBestInterface) (- q# Q0 V* _3 R K. Z) O
IPAddr dwDestAddr,
4 \% o: u6 P- k6 W- d PDWORD pdwBestIfIndex
5 P \& }8 z2 d8 K) R( U. h+ N w);
7 d/ d& v9 V2 C2 s1 h6 m4 [
; B- \; @7 L1 d: i3 R1 D( t8 b
9 |4 ?3 D' s; o4 T0 rtypedef DWORD (WINAPI* TGetIpAddrTable) (
: v3 b6 B$ ?; L5 p PMIB_IPADDRTABLE pIpAddrTable,% i/ `9 E/ R: W% h
PULONG pdwSize,( e ?# J) B7 F8 s/ h
BOOL bOrder2 }; {& s D. ~, a' x8 J6 U
);8 b7 h1 U5 ~( A: |( d( D; X; g
2 c+ a' J) Z2 j4 c( s
+ @8 x- j% J+ |7 U" vtypedef DWORD (WINAPI* TGetIfEntry) (
! X! C( r ~' B- N7 d) E PMIB_IFROW pIfRow
$ @1 F$ k% R4 a);
}+ c- S8 P% @% \
+ Z C8 R' {8 V& ]6 C" `2 T* n; v0 N) @% j/ v- N% H
CString translateUPnPResult(HRESULT hr);9 x6 W, }$ i3 M) a2 L
HRESULT UPnPMessage(HRESULT hr);& r# n3 R( v6 V% c- X; q, r' F
. ]+ H3 f) L. a( z+ n
7 v# R% A% h9 H7 p" ^
class CUPnPImplWinServ: public CUPnPImpl
: N2 l: @* k) X! a2 B: ?; ^{. i' x$ H# a% o& ]
friend class CDeviceFinderCallback;1 c4 F! [$ e. B; [6 u8 X
friend class CServiceCallback;0 W$ h7 I/ c! U( z8 L3 \/ q
// Construction
3 a( p) ^5 F0 t* z% Z; ?& v, Ipublic:
, U g* H3 b7 F! s& ~1 d$ d& Y virtual ~CUPnPImplWinServ(); O0 F2 q, N. z5 l* _$ }/ K N3 p
CUPnPImplWinServ();) z1 C2 V3 k9 J) x. w7 v- e
0 W6 q$ v0 p* v( a# O7 i* }
/ A! K4 p7 A, W( G! B% R* }# Z5 z virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }0 }" E: S" H' ^: U) t
virtual void StopAsyncFind();
( c7 @9 T$ D2 w& l# K virtual void DeletePorts();
: A9 _/ x- O9 p! J! L$ ~ virtual bool IsReady();
; e; O2 U; |* @ virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }
( x( m, x8 I; Q# S9 O, f4 S3 Q0 y- v+ [! t/ f: w
8 o) `! X: B& ?8 R* ` }2 y // No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)0 R, n6 l; p8 E, k ^* J! [
// the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later* |0 F# |, i+ s4 M+ Z U' i
virtual bool CheckAndRefresh() { return false; };* {0 V. S3 j8 b! Z
1 q0 x) a; \& Y: ~
9 t1 r4 s% K5 h3 }protected:5 v" U( ? [' V1 p. w. l
void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);
) T: }$ E5 F4 X& u void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);8 X- Q; n! ? g5 d! }
void RemoveDevice(CComBSTR bsUDN);
4 g# i" @9 }' f: d. f bool OnSearchComplete();0 |9 B$ T0 B0 |% @ Q* q* [
void Init();: c* V6 z/ T7 i* E
( O% N0 b2 |( P! ^
4 s( d6 E! P! U6 L5 v: M inline bool IsAsyncFindRunning() 7 T* P/ Z, U; k p- Z9 W3 p- m
{ U s0 P( q, g b$ }
if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )
, M( _# U8 t8 f, a; a; J" r {
$ x* I/ x: P+ X' g m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );+ Q# |3 U, o$ A1 _' r0 Y' S @
m_bAsyncFindRunning = false;6 m ~( r9 H! G( Y L, q( r
}4 @( y4 m5 ]& e
MSG msg;
- R8 ^; H4 S2 z) @2 { while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
/ T% K2 k9 b0 z& X7 x+ ~ {6 B- M9 C \: B: u
TranslateMessage( &msg );
" C, M( W0 @* f9 e0 I" [; [ DispatchMessage( &msg );
( H: }& V3 p: {6 S5 _& N8 o9 Q }
5 I. b) H" z4 }; M, F3 e4 v% |. m3 p return m_bAsyncFindRunning;
( x+ x; Q: t/ Y; O7 D+ } }. G3 N" U9 v e, E+ q/ N( Z
( N* K* ]0 B0 o& U7 N8 |
0 i5 [& K+ i% d TRISTATE m_bUPnPDeviceConnected;
' W9 L. q8 G$ D8 P* U5 D+ _$ [( l5 f' H( j1 w
- v; \* v( p( ~* D& F
// Implementation
& O: p% S9 p. f" j // API functions
+ K" ?7 X! @- P+ z+ }. l5 h; S7 ]( c SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);9 ]3 q( s0 }' v! ~9 r
SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD);
; S# n2 z) R: U, ^ BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);
5 i8 o' a# n( L! W/ D( l1 ^; m BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);5 ]0 x" r! L# X6 [6 S& `1 l
BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);, w! F P. L0 K
BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);
* `: C* n$ i: u* s ]9 o+ l! I1 Y# O' o$ [
% S+ n" \- d* N% T6 b* ]" _ TGetBestInterface m_pfGetBestInterface;* F5 }) t' p. G- a1 Y
TGetIpAddrTable m_pfGetIpAddrTable;. V6 \% g- g; ?9 L5 ?" W
TGetIfEntry m_pfGetIfEntry;# F Y F8 X% X% y; B
4 K7 h2 k% _% C7 i
6 Y3 O7 v8 p1 v5 t0 g7 k( |' c$ G static FinderPointer CreateFinderInstance();
5 x# o2 M. c5 K* |6 q struct FindDevice : std::unary_function< DevicePointer, bool >7 ]0 i9 V% o: ~( n9 ] M
{- H( o, T9 K! k" h, W% ^) S3 x) s
FindDevice(const CComBSTR& udn) : m_udn( udn ) {}% J4 `$ S. X8 P/ v: A
result_type operator()(argument_type device) const
6 `, k1 }; Q! f9 y9 ~ {1 J1 a) A% n5 c# }3 Z4 T+ _
CComBSTR deviceName;; e, L) N6 w, z" [6 E* V
HRESULT hr = device->get_UniqueDeviceName( &deviceName );
" U! H7 ^6 V# B* G
N6 p7 B) G' t! {$ }5 p; b* t! C3 |$ i% ?% w. p, i; P; M
if ( FAILED( hr ) )+ |! `0 D- J6 j0 j% x3 t
return UPnPMessage( hr ), false;
4 v7 H- ?- P7 {8 y8 h& H
) `0 Y7 w8 V4 o Y
9 g b) W& K& ]( {( Z0 e% z3 k return wcscmp( deviceName.m_str, m_udn ) == 0;
( X% i+ @( M" u! J8 A' D# H0 G }
( H3 k9 B. |5 d. g+ x CComBSTR m_udn;% t* D# z3 l- w. A8 X( O
};4 }- L! P/ p# R1 t c* [
d: U- y' ~$ T: b$ D9 B
void ProcessAsyncFind(CComBSTR bsSearchType);
% V/ ^" y3 c, n5 o/ P! @0 ^ HRESULT GetDeviceServices(DevicePointer pDevice);
: l' c( f* s0 r void StartPortMapping();
1 C) y# j9 B2 x* F" E3 | HRESULT MapPort(const ServicePointer& service);
/ f7 N3 `7 G3 o z% S P void DeleteExistingPortMappings(ServicePointer pService);5 E, u8 [2 R" B
void CreatePortMappings(ServicePointer pService);# ] Q7 j5 K9 O1 w
HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);
* b1 A! m5 O' u) v8 ~ HRESULT InvokeAction(ServicePointer pService, CComBSTR action, ( i& i% i9 v1 H$ z, V" a
LPCTSTR pszInArgString, CString& strResult);2 u) b" O) ~$ J4 |
void StopUPnPService();
. h0 N7 y6 x% f" l0 e3 C' ^( c* b; k" q9 r* m
9 @( U7 X" R: k
// Utility functions
8 d, S% {1 H. u/ @9 ~; o3 I9 k HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);
" K. j1 O8 S$ r' A+ Y INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);
2 h4 X5 }" p/ s9 T. Z INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);
( k# ^5 L# }4 M3 f0 m$ t void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars); N/ {! U4 E9 S/ `( j* w7 {6 i
HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);6 |( p$ y% R4 Z! h
HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);+ I/ C4 O. W6 [ D8 o9 k+ T
CString GetLocalRoutableIP(ServicePointer pService);! }* Z0 i- V/ [$ f. ~" \1 V+ f
* I7 J; ?4 w9 W1 m5 v
6 g/ k" G6 l: b( ]* Y K3 L* S! X
// Private members
* m# J# `7 B% f, T" Hprivate:* R4 I& G2 _3 B7 N# c* ~9 R
DWORD m_tLastEvent; // When the last event was received?
/ \8 e& e4 ~9 {$ G std::vector< DevicePointer > m_pDevices;; U3 [7 ^: e0 Z9 u8 f
std::vector< ServicePointer > m_pServices;
5 E: T" \7 M7 i! c9 q- l FinderPointer m_pDeviceFinder; k2 N6 h k" ^+ w
DeviceFinderCallback m_pDeviceFinderCallback;
: {# M3 Y4 ]0 z; m$ W. W/ M ServiceCallback m_pServiceCallback;
6 W' c4 S% j6 Z& t8 B% M5 U# Z- C$ e7 }7 h# N, c
: ]1 i7 y0 S4 N5 s5 m9 H
LONG m_nAsyncFindHandle;- s2 l9 p/ O2 A& F$ U* T X
bool m_bCOM; u$ m, X; Y9 }5 K2 ]
bool m_bPortIsFree;( `7 Y# B) q$ y+ U i3 q( D) Z: `* y
CString m_sLocalIP;5 A0 Z$ v5 t5 O5 D; V. g5 u
CString m_sExternalIP;
/ b) h1 H. i3 u1 N2 M bool m_bADSL; // Is the device ADSL?
6 L* Q6 i x0 _9 F d& H9 T& | bool m_ADSLFailed; // Did port mapping failed for the ADSL device?
1 \* L* ]3 P& |5 |. |! P bool m_bInited;$ b' f6 `% R7 o* T- y
bool m_bAsyncFindRunning;) s% g9 Q# W( z7 t5 O, ^7 T
HMODULE m_hADVAPI32_DLL;7 L; h4 M8 e$ t* B+ ~8 r
HMODULE m_hIPHLPAPI_DLL;
7 C! ? N! l8 J# [ bool m_bSecondTry;% z, X8 I$ D1 n6 G
bool m_bServiceStartedByEmule;0 l: P+ J( }. r
bool m_bDisableWANIPSetup;; ]5 @! v. A8 P! q* C
bool m_bDisableWANPPPSetup;
2 |' s+ [0 M( G, U2 |3 e; W1 q+ j" V8 } R
. |1 H7 X( s& @. _* y};1 `3 x; G0 }: Y, w6 `0 [
/ d8 p$ d4 a1 p( q! W I1 j; j& k% f* o6 G4 L3 T4 L B
// DeviceFinder Callback
s% K$ e J, T+ j9 I; B( ^& Fclass CDeviceFinderCallback
* g) S) a- L/ `5 y$ k! S7 n1 f : public IUPnPDeviceFinderCallback3 b" g* `# S3 U" l% Z' W7 g
{$ Y' J k" Y# p4 }3 t
public:! n4 a5 c. h4 h' ]0 c
CDeviceFinderCallback(CUPnPImplWinServ& instance)
' R- u5 {# z8 P : m_instance( instance )* F- J; p7 M- F
{ m_lRefCount = 0; }4 C4 j" O6 ?: |
. d' B5 B# n% _9 n! \
2 x* X2 B5 f# ` ?9 Z, V0 @6 l
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);1 Y% _" O9 r( H5 S+ ^+ z
STDMETHODIMP_(ULONG) AddRef();
) I- i/ o9 R. P, U8 r( P; s STDMETHODIMP_(ULONG) Release();
* T$ [& A7 w* g3 X7 m0 L8 o! F# n3 }2 X4 B
! I+ {, F' h, G+ J8 E1 h// implementation" U Q( b4 A' {) |7 }# A
private:
$ l6 A7 J5 g9 `% j/ d5 t HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);
9 `/ d+ d& W( [5 E; T" b- h7 G HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);7 h& H G! E& y/ A+ O. K
HRESULT __stdcall SearchComplete(LONG nFindData);& v1 R2 {4 _+ }2 v" \5 I% Z
; i3 m# |8 w* g3 ]
8 \5 T8 q( [6 G3 t: M
private:- w$ A: ?4 d# o5 _: X9 i
CUPnPImplWinServ& m_instance;; F D* T+ H; v
LONG m_lRefCount;; B2 u0 G3 \1 [! y' Z+ r
};+ m' g4 e% ?% n$ f* O/ g. k
8 ^* E5 U7 Z& H& k7 w; ~6 u
& o* M5 H! U& J5 N7 P+ m// Service Callback ) v) @) X- S+ G. I& L
class CServiceCallback
% s0 K+ r8 X: h( ~9 r9 b : public IUPnPServiceCallback
: Q$ g9 B# E: _1 G) _) Q{
, B8 |, q0 r$ J( \* Opublic:* A/ s% f) \* z. j
CServiceCallback(CUPnPImplWinServ& instance)5 V8 q8 a5 |: e% T
: m_instance( instance )9 Q4 a6 [ U- N8 I2 I: ^! G# W1 L
{ m_lRefCount = 0; }7 w# n( s3 L# b+ l7 c k
7 o" v- ~0 I6 ^, C* k
STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);
1 T! X C+ P$ \# O$ s5 ~2 } STDMETHODIMP_(ULONG) AddRef();6 J$ a! e) |" o |0 Q1 j
STDMETHODIMP_(ULONG) Release();
. L5 u% f' H/ J4 K: W
1 q2 z: s$ V7 l X- `) ]" c# u! E M4 o5 D2 L( k3 S2 o& H7 ?' Q# E
// implementation
; M8 ]" i+ Y. Z- e n1 L6 d; `6 lprivate:
0 C/ _3 q. Z6 _; H0 w0 _ HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);
0 E- _& o( ], H HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);
C7 @# T' T: ^" N/ Q' X
! _( y, O$ u/ H2 h$ C+ R! z
) p6 X0 X; A: N9 Iprivate:
k, Y5 |- V/ D! r CUPnPImplWinServ& m_instance;
' z, {6 o7 N6 y# C8 _ LONG m_lRefCount;
: t' g4 F# E2 G( M Y( m};
5 @& s6 A" {4 x) Q0 P& p; ?' a
1 I. D" Y/ ~. ] @
$ Y! H* m3 s y/////////////////////////////////////////////////
4 b2 S- C9 {8 P" r5 h& O8 ]; C/ b, g1 K( G# G/ n3 ~5 p- W) h
( n3 h& D# l9 U7 R1 J
使用时只需要使用抽象类的接口。4 B) d8 d5 y6 i& B: V
CUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID.
) \" Z2 R9 l; }' PCUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.
3 E6 l b' B" s3 Z( ?; N6 o( KCUPnPImpl::StopAsyncFind停止设备查找.
5 W+ E5 [, S( d9 l6 o. s+ jCUPnPImpl::DeletePorts删除端口映射. |
|