|
|
楼主 |
发表于 2011-7-15 17:28:52
|
显示全部楼层
以下有关upnp的接口来自emule, Y- d9 h6 Z. X4 i$ C
- y! A+ r A, _% L5 Q! `! ]: M
$ L# w0 g9 s' k$ N; }; V///////////////////////////////////////////
' j8 n" Y$ h8 Q1 ^' E. O# }+ R% K//upnp的抽象接口类,只需调用这些接口即可实现端口映射功能.
9 W+ O6 q% \, y. D
% m9 e5 u# @( M) v2 K$ ?& b J$ c; m8 D
#pragma once
# Y* f! R' @6 c# T. D4 P#include <exception>: S$ Y5 Q; t* R
, }! B+ ~% z; [* W) q) R1 H+ t" {1 f( g/ r; n- C3 s% y
enum TRISTATE{0 ^3 i& W5 s( _4 h7 \5 w
TRIS_FALSE,5 [" ~ q5 ]8 }" `) X
TRIS_UNKNOWN,
; j8 ?3 L( ^/ r5 f) }+ ? TRIS_TRUE
( [# W# [! V! H};
! a8 a. _! ]# F$ V* Z
" F# W6 Q; L( Z
" Y1 ~6 X" S' f) A4 {7 X: P' venum UPNP_IMPLEMENTATION{
3 O( T8 J$ S5 ]( o& f' |3 s UPNP_IMPL_WINDOWSERVICE = 0,
, v" }, R+ c' I0 q UPNP_IMPL_MINIUPNPLIB,
7 B H; ~1 Z3 D4 Q9 {6 `3 O1 H UPNP_IMPL_NONE /*last*/( H7 `; [& I6 m. j* @6 A- q" P
};
2 h/ B2 T! C1 A1 {
/ T2 Z- y4 X8 b$ a
) b; l/ T$ l T; L% x5 g5 E. ?
2 ]8 m" z9 A6 J* H$ }% y. g* w
, Z k8 H, G8 u, |; G. v% Hclass CUPnPImpl" a8 V0 _+ b8 Q5 S& [
{# r7 t7 l8 r' L4 l
public:$ L$ Y; v* }% y" Z& P5 m, N# e( V
CUPnPImpl();
3 F' Z2 F( O+ w# G( N virtual ~CUPnPImpl();
: m% Y% M3 r w8 G( Z9 [# F struct UPnPError : std::exception {};
. u3 c) n; l( \2 K% t ] enum {
3 J) `0 j2 [4 E UPNP_OK,
, S8 x* W: w. ?2 c& e UPNP_FAILED,% Y, e4 l4 s$ N1 V7 E
UPNP_TIMEOUT
6 `+ p9 v$ G$ q) | }; c. ]4 n" e' s9 B& u! A7 E
' t0 W# W4 ^6 D/ a
3 y: |) P" b* I8 |- N virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) = 0;# f a7 k( N% a; h' z. g/ R
virtual bool CheckAndRefresh() = 0;0 b: F# a* G3 E8 {
virtual void StopAsyncFind() = 0;, V, e5 V' C- J5 g! n) ^4 x# \
virtual void DeletePorts() = 0;; U8 D+ ?; v2 X3 W0 V" b9 }
virtual bool IsReady() = 0;
5 m$ ~. k" Q; ]6 `' M virtual int GetImplementationID() = 0;
( `2 N0 h% c7 ~6 L0 D- Y - e0 J5 ?: o) L, B; \* i7 s3 G6 _% x
void LateEnableWebServerPort(uint16 nPort); // Add Webserverport on already installed portmapping& D+ F; q3 x& P( w" u9 U! r3 J0 o
+ X8 r0 ^- S5 ~" g3 f/ V' c* g0 X- }, m7 Y" b7 C
void SetMessageOnResult(HWND hWindow, UINT nMessageID);
8 K, d' J" v' S TRISTATE ArePortsForwarded() const { return m_bUPnPPortsForwarded; }
- X9 X& T5 n2 l; N: | uint16 GetUsedTCPPort() { return m_nTCPPort; }
$ y% r: J% A6 ]- i6 h- ? uint16 GetUsedUDPPort() { return m_nUDPPort; } ; d5 A1 I* b+ F8 |1 L
6 o: M& \8 g9 U7 U+ O! ]6 u3 z; H
// Implementation' ]2 e) ]- w R( r
protected:+ D# b0 G4 \2 f3 e9 C
volatile TRISTATE m_bUPnPPortsForwarded;
1 e) X$ [/ V% ]/ R6 e void SendResultMessage();3 x0 }) a3 F6 Q$ N. {1 }
uint16 m_nUDPPort;) u7 x; H6 ?: }0 v1 T: \
uint16 m_nTCPPort; I: g: v9 F- c5 e
uint16 m_nTCPWebPort;
# `% \$ T; Z# U bool m_bCheckAndRefresh;8 n+ a, M3 s# F! ]2 Y* d: `6 Y- d
3 W$ W' R( q! \9 N' {% M$ V5 }) G) ~5 Q. q
private:
2 W: @2 N W9 |; A& D/ _3 d/ P+ a& k r HWND m_hResultMessageWindow;4 \+ T& \7 e* T! p1 q2 J
UINT m_nResultMessageID;4 {$ _/ m2 m6 |- `8 p. l& X1 L
, l; T- \9 G6 I+ |* S
" o2 Q) B. U6 L; O2 V1 V/ p};
9 X* o2 L& X7 c" h& ?! ^1 |* w$ j- s) H- l$ ?3 X
" I. h$ Q2 A+ k T
// Dummy Implementation to be used when no other implementation is available' t" s0 h; O% @3 Z7 y
class CUPnPImplNone: public CUPnPImpl
4 p1 _2 v: J, f) \& k% Z' p0 p{
/ i& A3 W& A" Y- g( Y4 [public:" @ [3 k- Q4 l/ R
virtual void StartDiscovery(uint16, uint16, uint16) { ASSERT( false ); }/ H( ?+ j$ T! k4 g5 }9 H# ~, a1 o: j$ |
virtual bool CheckAndRefresh() { return false; }
. g: b* j4 s- |: R virtual void StopAsyncFind() { }
W4 k; I* _# m& a2 ?( `: w/ y virtual void DeletePorts() { }
# p9 \* X. V ]+ p* }5 q virtual bool IsReady() { return false; }
4 t- ?/ r5 j8 Y$ `- j3 A virtual int GetImplementationID() { return UPNP_IMPL_NONE; }
5 a' T# h7 w# f' Q3 S$ P& }};
/ C; u9 f" k0 N! t9 B8 J* g
7 W: l6 b" W! G5 Q4 ?' F D: z C( T6 E4 s) j, a0 h& z
/////////////////////////////////////
`9 ~6 Q6 f, y; Q- `//下面是使用windows操作系统自带的UPNP功能的子类
( L) Q% h2 g4 {; O
; t2 E$ X0 W0 ? d5 s3 n
' c" Y: D7 S {4 p, W: J. n#pragma once
$ S+ a: l/ H3 D3 u, z5 {( Q#pragma warning( disable: 4355 )
( j f9 B6 I5 p2 M: A! L1 ^. r2 ]0 Q
_' N6 P" G5 Q7 f
#include "UPnPImpl.h"' `% o% S, Z, l0 k& g# A' g# W" G( r
#include <upnp.h>) n, R; x2 O: H4 \& F; d4 c
#include <iphlpapi.h>" K5 [" J- @5 M0 e: f0 R; P4 @
#include <comdef.h>) i' T- x# B! Y F2 T1 | Y- _9 B
#include <winsvc.h>
; r* u! L8 L3 Q) U5 t- O; {! F! H( g
4 ?; y- I. g6 |$ [#include <vector>0 }5 C/ Q$ Y1 M4 g( |1 P
#include <exception>
# R0 q% v) _; l8 @ M#include <functional>
1 H1 I: e. z2 y, V
! U/ ^7 u' x" g
1 X* t) j4 c- q" h/ m9 i+ F. B1 n) E
, z8 z$ L3 t, \/ G$ ~/ ttypedef _com_ptr_t<_com_IIID<IUPnPDeviceFinder,&IID_IUPnPDeviceFinder> > FinderPointer;
' L; b( Y; B6 o2 V* I y$ Utypedef _com_ptr_t<_com_IIID<IUPnPDevice,&IID_IUPnPDevice> > DevicePointer;1 {# L6 }2 T; q4 l1 X! C8 z5 ?
typedef _com_ptr_t<_com_IIID<IUPnPService,&IID_IUPnPService> > ServicePointer;, d: d! p$ V9 Q2 |- |8 `9 x; W
typedef _com_ptr_t<_com_IIID<IUPnPDeviceFinderCallback,&IID_IUPnPDeviceFinderCallback> > DeviceFinderCallback;
% R2 k' v! S% S' ntypedef _com_ptr_t<_com_IIID<IUPnPServiceCallback,&IID_IUPnPServiceCallback> > ServiceCallback;, J0 ~+ k5 ]0 q o
typedef _com_ptr_t<_com_IIID<IEnumUnknown,&IID_IEnumUnknown> > EnumUnknownPtr;2 T% I* l$ g8 N% F, k3 q$ e3 M
typedef _com_ptr_t<_com_IIID<IUnknown,&IID_IUnknown> > UnknownPtr;( @! Y, U! n' n
) Y Z7 [ G3 L; G# f
2 s! m! a8 U* ^typedef DWORD (WINAPI* TGetBestInterface) (
- [5 y# A- z0 e" G" y IPAddr dwDestAddr,
$ g5 }- @: G" a/ P PDWORD pdwBestIfIndex
. ]1 v8 e3 h! ?0 p+ S7 p& K" y' b);& z3 `7 U7 x) i7 [8 i
7 Z) K% {# z# ^- I7 O O3 ]
1 q5 q' U4 n4 i$ q! {. Q7 y Otypedef DWORD (WINAPI* TGetIpAddrTable) (' Z9 h0 a5 i! p- ?3 g! y t9 X
PMIB_IPADDRTABLE pIpAddrTable,/ t6 _) n9 R$ `& X/ a h+ U
PULONG pdwSize,( L) J/ T) ]5 G
BOOL bOrder6 u- @. _5 @8 T. A- q
);
0 H( E/ |! A2 ?1 ?( Z- n8 ]) p3 j
" {5 Y' f, R: m2 r9 m
typedef DWORD (WINAPI* TGetIfEntry) (
5 ~: S, z- \' V+ I* {6 m3 n PMIB_IFROW pIfRow
- G' B. z) |" b- v; j9 n7 j);
0 t5 G7 V7 g5 K! E" S. K
% X2 |/ ~! R- p {' b5 L( ]2 e9 p4 g6 C
CString translateUPnPResult(HRESULT hr);2 d; ?' T" R; [, K. k3 T; k
HRESULT UPnPMessage(HRESULT hr);
( d1 Z; A; |+ o/ ~0 C1 a$ M6 l% l' |' _; b6 \! m r
7 L- R( Q0 }, L; }/ z- F
class CUPnPImplWinServ: public CUPnPImpl
* v; c- E+ z* V4 l5 G{% |& B. u* z/ T$ e3 {/ r
friend class CDeviceFinderCallback;7 m Z7 Z& J Z5 u( D& H$ r3 h
friend class CServiceCallback;- O1 h- j' ^4 Y# Y. z
// Construction% m' L4 H0 q! t w! p, N [
public:
( n6 E, p3 d: c6 L5 v4 o# q virtual ~CUPnPImplWinServ();
9 x4 ~! ^) R0 W( z CUPnPImplWinServ();. W1 `# w# J; r6 y" a
, O& p8 f0 ~. X, @6 [/ L- J) `" a/ p4 H" x4 b$ x& e
virtual void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort) { StartDiscovery(nTCPPort, nUDPPort, nTCPWebPort, false); }
7 K$ ~' N M5 E; {7 _ virtual void StopAsyncFind();
" ?9 a% h5 v& z6 Y; D m; N( P virtual void DeletePorts();
- c! ]* a- V* l% t; Y virtual bool IsReady();
% L6 Z6 Z9 E1 h- J8 |+ _' n virtual int GetImplementationID() { return UPNP_IMPL_WINDOWSERVICE; }
/ y8 x- F1 e7 o; q4 w8 O7 |* t) u! \& y6 x
! z, h0 h. E3 e( }% B
// No Support for Refreshing on this (fallback) implementation yet - in many cases where it would be needed (router reset etc)
" ^1 `4 r4 x: r& I- z' y // the windows side of the implementation tends to get bugged untill reboot anyway. Still might get added later
# A/ E6 }; W9 j, E virtual bool CheckAndRefresh() { return false; };
8 t% G0 d% r' a4 ?: ^5 H) I
) @" o- _! k8 x. n" `+ r8 F7 B3 j: q) k
protected:4 F+ Z. \. B6 H; D/ L' H
void StartDiscovery(uint16 nTCPPort, uint16 nUDPPort, uint16 nTCPWebPort, bool bSecondTry);
" A& v! x0 g {/ O void AddDevice(DevicePointer pDevice, bool bAddChilds, int nLevel = 0);" M! M. f% Q3 E0 \$ l9 B
void RemoveDevice(CComBSTR bsUDN);
* Q: } o: M/ K, w/ e3 N bool OnSearchComplete();
7 ]3 M, ~' ~1 h& x$ q void Init();
- L, l" w" p1 i4 x) @8 K
% g+ d) ~! l% K' J$ i; ]3 c: W& \- B; w
inline bool IsAsyncFindRunning() 0 ]) Q; h6 R- b/ F
{1 {0 G: \6 Y, E" c
if ( m_pDeviceFinder != NULL && m_bAsyncFindRunning && GetTickCount() - m_tLastEvent > 10000 )
0 S1 ~7 [) { p1 { {
- m! r* k) ?/ Y+ H/ r m_pDeviceFinder->CancelAsyncFind( m_nAsyncFindHandle );3 b3 m( V6 k5 W' K
m_bAsyncFindRunning = false;
" e0 D$ E4 T8 m% Z4 H$ f/ i }
; X) I. |8 k( \3 p' ^* J MSG msg;
0 X4 p! F" w$ I2 l8 z5 G; A while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
2 _) |" e" U- i1 j# }- b {) I1 M; {! {, }4 [. |3 `
TranslateMessage( &msg );" i, U" L2 \. o7 ^* B# |4 c
DispatchMessage( &msg );
% c; O2 V6 } b/ ^8 _, D8 @/ M }
/ x/ `; D8 k- h6 q return m_bAsyncFindRunning;! ^( j T8 `# ^0 G+ ]% K9 g: L
}' `2 q! Y& c; G) i, K+ v
4 _1 }# B& R- Q* m' g) w2 G7 S6 _+ U, O B& ^
TRISTATE m_bUPnPDeviceConnected;
, J) _' K( z+ H e
3 j, l" q& r! b2 |( r9 P3 x
& W" l: f, p0 s; \// Implementation: }* K9 M x8 N) J6 x
// API functions
! T7 q0 o; B( k0 g SC_HANDLE (WINAPI *m_pfnOpenSCManager)(LPCTSTR, LPCTSTR, DWORD);
# o4 j0 @8 y/ Y9 f8 Z SC_HANDLE (WINAPI *m_pfnOpenService)(SC_HANDLE, LPCTSTR, DWORD); F/ g" y4 f6 z. E/ |
BOOL (WINAPI *m_pfnQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD, LPDWORD);0 U4 [& ]/ a* x$ P: o: A0 P- [
BOOL (WINAPI *m_pfnCloseServiceHandle)(SC_HANDLE);! s3 D9 s6 f9 }
BOOL (WINAPI *m_pfnStartService)(SC_HANDLE, DWORD, LPCTSTR*);% f$ G1 _! w4 T8 }4 r
BOOL (WINAPI *m_pfnControlService)(SC_HANDLE, DWORD, LPSERVICE_STATUS);: b X' e: P& D! j- i1 k4 R& S
+ d. n9 H' A: |$ N! ]" h
' G0 u5 \8 h; L( I( d# n TGetBestInterface m_pfGetBestInterface;
3 l# [( u' f- j0 q TGetIpAddrTable m_pfGetIpAddrTable;
$ s( l+ D' ?1 F TGetIfEntry m_pfGetIfEntry;% N7 F; n4 t7 m' `1 {/ V% Q9 v+ ?0 n
! Q8 J- }9 v: j' ~' V' T
0 B. m3 `. R& |) N0 h4 r } static FinderPointer CreateFinderInstance();4 Z! K& G" t" \9 c/ K
struct FindDevice : std::unary_function< DevicePointer, bool >. q0 e2 r7 j/ D- c
{
6 d) i( t2 B0 F+ d FindDevice(const CComBSTR& udn) : m_udn( udn ) {}
4 l0 G! z. H2 q. B: Z( I/ G result_type operator()(argument_type device) const6 p/ Z3 C4 q Z+ W6 o7 K; D0 u
{
5 Z" @ y. z9 F0 y# y x CComBSTR deviceName;) Z* E# L3 V) z- Q3 }
HRESULT hr = device->get_UniqueDeviceName( &deviceName );
, W0 Y5 q5 B. ]0 c% k0 I3 E! f& \$ n' o# H5 s' {
! D" ]/ Q5 x+ Q: u0 o; p% h if ( FAILED( hr ) ); W1 a: ^! f; S+ X
return UPnPMessage( hr ), false;& P$ U' i6 I7 b
" L3 S. V* k( p: x8 \4 B4 e4 Q
. w2 G: e6 d7 H5 w8 w7 n# R! } return wcscmp( deviceName.m_str, m_udn ) == 0;
- N$ p9 P: b1 Q& c }1 W3 j, r* R( f! S" X: i) W7 p. l
CComBSTR m_udn;4 H7 R3 L/ E+ w+ l
};- x4 _0 E- @+ Q& f2 A) I$ C
$ Y2 M' e/ ]- t! r9 |
void ProcessAsyncFind(CComBSTR bsSearchType);1 T) y8 b8 v' A3 J3 n* X4 T
HRESULT GetDeviceServices(DevicePointer pDevice);) U6 I, J- |8 p2 h
void StartPortMapping();
6 Y7 W$ |# y; V" n3 {7 |. v HRESULT MapPort(const ServicePointer& service); ~! M2 F0 @" V/ Q$ r6 T
void DeleteExistingPortMappings(ServicePointer pService);
6 ?; u5 j2 V" n8 t' P8 w2 Z' I void CreatePortMappings(ServicePointer pService);
B, s9 b) A( K$ ?9 A: F8 |$ c8 | HRESULT SaveServices(EnumUnknownPtr pEU, const LONG nTotalItems);
- C$ h0 V6 M5 J7 R0 d z% u3 U HRESULT InvokeAction(ServicePointer pService, CComBSTR action,
" y' ^+ L& B4 h" C* R LPCTSTR pszInArgString, CString& strResult);+ [+ k3 l6 F) _1 J1 ?+ }
void StopUPnPService();
5 R- L7 Z" i7 g: W
! r4 I" m/ w$ h0 [! f$ q; E$ g9 c$ O( D8 i6 }8 b, O7 b
// Utility functions
; ^. y, D. V$ j, Z- T' R HRESULT CreateSafeArray(const VARTYPE vt, const ULONG nArgs, SAFEARRAY** ppsa);3 F* A( T4 S1 w# w
INT_PTR CreateVarFromString(const CString& strArgs, VARIANT*** pppVars);
" D ]) b& ` L1 T9 B& j INT_PTR GetStringFromOutArgs(const VARIANT* pvaOutArgs, CString& strArgs);# a0 p, a9 K- @: A' `0 {- {
void DestroyVars(const INT_PTR nCount, VARIANT*** pppVars);. F- X/ M6 M2 ]0 @
HRESULT GetSafeArrayBounds(SAFEARRAY* psa, LONG* pLBound, LONG* pUBound);- F2 \+ ~* f" F N
HRESULT GetVariantElement(SAFEARRAY* psa, LONG pos, VARIANT* pvar);
) p2 O% U$ c5 ^$ H, x, t3 d; U CString GetLocalRoutableIP(ServicePointer pService);
- B0 ^7 U: {' F$ m, W
1 ^1 Y/ X/ k9 @5 f C) D) j# L* N+ T: `0 i0 _( q
// Private members
& x# H# R( L& Qprivate:
' ~, t- s1 r: D% ?1 ^0 m DWORD m_tLastEvent; // When the last event was received?
+ {. r1 t2 U& S2 O& z std::vector< DevicePointer > m_pDevices;
$ ~: j& x* q, z3 R( R& D6 e std::vector< ServicePointer > m_pServices;
! a+ p& `! i) I( e$ P FinderPointer m_pDeviceFinder;. r3 @2 H# |5 p. ~# r
DeviceFinderCallback m_pDeviceFinderCallback;6 Q4 v9 {: Z) T4 V' Z
ServiceCallback m_pServiceCallback;
& L8 J. a4 t/ e" [9 r: d2 }
: g/ Q. {* L1 p: n
5 x5 _& `; s7 N$ t4 ~6 H( P LONG m_nAsyncFindHandle;0 V* X+ F: p3 L9 `& f
bool m_bCOM;7 D; R- ~+ d) ?3 [: k/ u
bool m_bPortIsFree;
. r& j% ?% Y4 z# B7 }+ e' l CString m_sLocalIP;; D+ I0 p" z0 |6 a: x7 q
CString m_sExternalIP;
l' O! r3 g! w/ _) U8 V. B5 }: x bool m_bADSL; // Is the device ADSL?
/ x) [) g( X! t* l bool m_ADSLFailed; // Did port mapping failed for the ADSL device?
; y; O' A) s7 S3 ]& d bool m_bInited;
" Q2 i3 K* b4 L5 t bool m_bAsyncFindRunning;# a7 K) [1 o3 w- F" k% r
HMODULE m_hADVAPI32_DLL;
- c8 O" T2 Z' }) G- _* [ HMODULE m_hIPHLPAPI_DLL;
/ ~; ~! P1 v* z4 t2 R0 z8 y+ V, l+ i( v bool m_bSecondTry;
9 L! i8 m* n! M bool m_bServiceStartedByEmule;
) j: j; k3 B5 | bool m_bDisableWANIPSetup;
1 ?& _. m6 }( o" {6 q2 M bool m_bDisableWANPPPSetup;
3 B7 m( ^6 T" s; A3 w/ B7 U
+ z4 D$ X5 M8 V' }4 _$ A: R7 e& @1 V7 H$ a
};
! |/ i2 U ^$ x, _
; f `' _. W f( C( e* F$ [) u
$ E0 @' J f3 A* Z) h// DeviceFinder Callback9 k+ U2 K, L. z% x& w
class CDeviceFinderCallback
8 a/ c. [% S4 l : public IUPnPDeviceFinderCallback
2 K3 t F7 _4 o! H+ ~3 O{
9 d- t; n+ G. C- E' j0 xpublic:
, {) a8 Q' I( S' x CDeviceFinderCallback(CUPnPImplWinServ& instance)- }% O6 u( {! R7 Z; [. v
: m_instance( instance ), _1 J& S6 K u: x* x
{ m_lRefCount = 0; }
% e! ~& l, t G0 f( L& ], @. k7 F1 E2 `, g% W
4 i" E/ j! [2 H3 Q2 ?1 _; q, O1 ~ STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);' @* K" o$ G2 a4 O: r; J8 [' }
STDMETHODIMP_(ULONG) AddRef();
2 t- c+ {! |( z: `0 z" ^+ ^) n0 F STDMETHODIMP_(ULONG) Release();4 F8 S6 B( F# s5 h% i. u) s
( U, h5 z, v; {+ r2 U8 i, n( i1 @% C# x/ z2 S
// implementation
) j3 d* k. {% `! }private:$ a4 S" L$ W! R# o. ~" I, R
HRESULT __stdcall DeviceAdded(LONG nFindData, IUPnPDevice* pDevice);9 t' C% X u; ^6 G0 X/ y( T' {: m- G3 ~
HRESULT __stdcall DeviceRemoved(LONG nFindData, BSTR bsUDN);6 u+ m$ m5 v3 F: P1 S& p+ H' j3 S
HRESULT __stdcall SearchComplete(LONG nFindData);2 x$ w; E1 b' \$ b
0 [ C' @2 U2 o
8 L: n0 w' n- _0 g& g( b# nprivate:
+ J2 \# E4 u4 {, l+ O/ X$ f5 F CUPnPImplWinServ& m_instance;' D$ E( _3 G! H+ A8 J- m) p
LONG m_lRefCount;
. a1 P3 q4 C, I7 G6 x};* V% }- L6 F3 [4 R' e, Z6 S
8 b; O) f5 m4 P' G) Y# v
& N9 j% `3 @2 k
// Service Callback
4 V3 \! B3 C* J& {$ @1 [+ @class CServiceCallback
: d. B5 ]- o7 f) _ : public IUPnPServiceCallback
' v4 F, s# X M; [/ y{4 }; Z7 }4 ` Q. \
public:8 M: S2 C% X$ ]- ~6 L$ Z7 K' \
CServiceCallback(CUPnPImplWinServ& instance)
6 Z& t0 M3 `( r" G: E : m_instance( instance )
: U/ M5 ^% p2 p' b { m_lRefCount = 0; }
& p8 `$ R( H7 W. S
/ Q- o4 ?$ D) _ W. ?4 { STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject);" o, B1 \; d4 f$ d; j; J
STDMETHODIMP_(ULONG) AddRef();* H- v: U$ P1 n
STDMETHODIMP_(ULONG) Release();* X4 B3 r J8 K1 E$ O( E
# P6 i& t7 y) w" |
# i7 P0 q: X0 v// implementation
6 [/ s8 U- |. _: K7 h: S2 N ?& A& }private:
. I+ n3 I! Z$ h# _* i% i7 z& l% ^ HRESULT __stdcall StateVariableChanged(IUPnPService* pService, LPCWSTR pszStateVarName, VARIANT varValue);/ ^ G6 o) c/ I1 q. a- [% e) i
HRESULT __stdcall ServiceInstanceDied(IUPnPService* pService);4 R0 |' |. I7 @. K) \
! ?% U( @/ r; F
! w7 l! f/ i" Q4 J1 o( a& R
private:# W4 w( `9 j6 h) h' N
CUPnPImplWinServ& m_instance;
$ M, U3 w0 s; v, k9 Q) S& e LONG m_lRefCount;
2 Q5 V* j2 ~" [3 V};7 u# M# G( o* o& E1 h5 R3 C
( u$ h/ \# h) ^3 I' t
0 ]- g% p0 n- O( Y& A
/////////////////////////////////////////////////; M" M* c1 L: C- r0 M) k
7 W* e) l" z# w; ~2 U' `( B4 e/ Z& N
. _ i+ g8 S+ s6 i
使用时只需要使用抽象类的接口。+ ]# @6 K# [- O# ]! @1 I
CUPnPImpl::SetMessageOnResult设置需要接受UPNP端口映射是否成功的窗口句柄和消息ID., n- H# X$ O6 o& ]4 k6 t- e+ X
CUPnPImpl::StartDiscovery将开启一个异步设备查找并进行端口映射,其参数为需要映射的内网端口.
& S. {/ q+ R( U# FCUPnPImpl::StopAsyncFind停止设备查找." ]0 N& S0 D6 J8 K. h0 o
CUPnPImpl::DeletePorts删除端口映射. |
|